1,wxpay.php 微信小程序支付(微信公众平台),微信公众号支付大同小异。希望对大家有所帮助,谢谢!内容如下:<?php
//微信小程序支付代码详解
//第一步,下单 支付前需要下单,调用了两个方法wxpay和wxapi
/**
*微信下单
*/
function wxorders(){
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
$kilometre = $_POST['kilometre'];
$km = $kilometre/1000;//米数转化成公里
//提交订单
$data = array(
'start_address'=>$_POST['startLoca'],//出发地址
'end_address'=>$_POST['destLoca'],//目的地
'start_time'=>strtotime(str_replace('.','-',$_POST['startTime'])),//开始时间
'end_time'=>strtotime(str_replace('.','-',$_POST['endTime'])),//结束时间
'km'=>$km,//公里数
'seat'=>$_POST['seat'],//座位
'borad_price'=>$_POST['basicPrice'],//上车价
'per_km'=>$_POST['perKiloPrice'],//每公里单价
'total_price'=>$_POST['cost'],//总价钱
'contact'=>$_POST['name'],//联系人名
'mobile'=>$_POST['phone'],//联系电话
'status'=>'1',//状态
'create_time'=>time(),//提交时间
'type'=>$_POST['type'],//租车类型 小bus 大巴等
'kelala'=>$_POST['session_key'],//标识符
);
$total_price = $_POST['cost'];//总价赋值
//插入订单记录,此处状态为待付款
$res = $this->baseModel->add('orders',$data);
//根据标识符查询当前账号的openid
$kelala = $_POST['session_key'];//用户的唯一标识
$user = $this->baseModel->getRow('user','*',array('kelala'=>$kelala));
//调用下单接口 $res为新订单的id
$r = $this->wxpay($total_price,$user['openid']);
//分别传总金额,用户openid,前面生成的订单id
$a = $this->wxapi($total_price,$user['openid'],$r['prepay_id'],$res);
//这里返回结果集合到前段,前段根据返回的参数调用微信支付界面,并且返回成功失败给后端,需要另外写接口接收
echo $a;exit();
}
/**
*微信下单
*@param total_price 下单金额 单位为/元
*@return 这一步返回prepay_id
*@param $id为新订单的id
*/
function wxpay($total_price,$openid){
//拼接商品订单号
$body = '测试商品';
$out_trade_no = date("YmdHis") . rand(100, 999);
// //更新微信返回的订单号
// $this->baseModel->updateById('orders',array('out_trade_no'=>$out_trade_no),$id);
$order = [
'appid'=>'',
'mch_id'=>'',//商户id
'openid'=>$openid,
'nonce_str'=>$this->rand2(10),
'body'=>'测试商品',
'out_trade_no'=>$out_trade_no,//商户唯一订单号,可包含字母序
'total_fee'=>$total_price*100,//订单金额,单位/分所以乘以100
'spbill_create_ip'=>'123.12.12.123',//产生订单号的服务器IP
'notify_url'=>' ',//接受微信异步通知地址
'trade_type'=>'JSAPI',//交易类型
];
//MD5处理,默认支持MD5
// $sign = md5($sign);
$order['sign'] = $this->getSign($order);
//转换成一维XML格式
$xml = '<xml>';
foreach($order as $k=>$v){
$xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>';
}
$xml.='</xml>';
//CURL会话
$ch = curl_init();
// 设置curl允许执行的最长秒数
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
// 获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
//发送一个常规的POST请求。
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, ' ');
//要传送的所有数据
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
// 执行操作
$response = curl_exec($ch);
//将xml格式的$response 转成数组
$response = json_decode( json_encode( simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA) ), true );
return $response;
}
//第二步,再次签名
/**
*再次签名
*@param $total_fee 下单金额
*@param $openid 当前用户openid $order_id 下单时传来的id
* @param $id为新订单的id
*/
function wxapi($total_fee,$openid,$order_id,$id){
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
$out_trade_no = date("YmdHis") . rand(100, 999);
//更新订单状态 此处状态更新为1
$this->baseModel->updateById('orders',array('out_trade_no'=>$out_trade_no),$id);
if(empty($total_fee)){
echo json_encode(array('state'=>0,'Msg'=>'金额有误'));exit;
}
if(empty($openid)){
echo json_encode(array('state'=>0,'Msg'=>'登录失效,请重新登录(openid参数有误)'));exit;
}
if(empty($order_id)){
echo json_encode(array('state'=>0,'Msg'=>'自定义订单有误'));exit;
}
$appid = '';//如果是公众号 就是公众号的appid;小程序就是小程序的appid
$body = '测试数据';
$mch_id = '';//商户id
$KEY = '12ed7bd47d66f4ef7865f79b2194a94b';//加密的字符串 在公众号平台设置
$nonce_str = $this->rand2(10);//随机字符串
$notify_url = ' '; //支付完成回调地址url,不能带参数
$out_trade_no = $out_trade_no;//商户订单号
// $spbill_create_ip = '123.12.12.123';
$spbill_create_ip = $_SERVER['SERVER_ADDR'];
$trade_type = 'JSAPI';//交易类型 默认JSAPI
//这里是按照顺序的 因为下面的签名是按照(字典序)顺序 排序错误 肯定出错
$post['appid'] = $appid;
$post['body'] = $body;
$post['mch_id'] = $mch_id;
$post['nonce_str'] = $nonce_str;//随机字符串
$post['notify_url'] = $notify_url;
$post['openid'] = $openid;
$post['out_trade_no'] = $out_trade_no;
$post['spbill_create_ip'] = $spbill_create_ip;//服务器终端的ip
$post['total_fee'] = intval($total_fee); //总金额 最低为一分钱 必须是整数
$post['trade_type'] = $trade_type;
$sign = $this->MakeSign($post,$KEY); //签名
$this->sign = $sign;
$post_xml = '<xml>
<appid>'.$appid.'</appid>
<body>'.$body.'</body>
<mch_id>'.$mch_id.'</mch_id>
<nonce_str>'.$nonce_str.'</nonce_str>
<notify_url>'.$notify_url.'</notify_url>
<openid>'.$openid.'</openid>
<out_trade_no>'.$out_trade_no.'</out_trade_no>
<spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
<total_fee>'.$total_fee.'</total_fee>
<trade_type>'.$trade_type.'</trade_type>
<sign>'.$sign.'</sign>
</xml> ';
//统一下单接口prepay_id
$url = ' ';
$xml = $this->http_request($url,$post_xml); //POST方式请求http
$array = $this->xml2array($xml); //将【统一下单】api返回xml数据转换成数组,全要大写
if($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS'){
$time = time();
$tmp=''; //临时数组用于签名
$tmp['appId'] = $appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id='.$order_id;
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = (string)$time;
$data['state'] = 1;
$data['timeStamp'] = (string)$time; //时间戳
$data['nonceStr'] = $nonce_str; //随机字符串
$data['signType'] = 'MD5'; //签名算法,暂支持 MD5
$data['package'] = 'prepay_id='.$order_id;
// = 'prepay_id='.'wx20180314162441c9c0b517a40292406177'; //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = $this->MakeSign($tmp,$KEY); //签名,具体签名方案参见微信公众号支付帮助文档;
$data['out_trade_no'] = $out_trade_no;
}else{
$data['state'] = 0;
$data['text'] = "错误";
$data['RETURN_CODE'] = $array['RETURN_CODE'];
$data['RETURN_MSG'] = $array['RETURN_MSG'];
}
//此处返回结果集合
return json_encode($data);
}
//第三部,上面三个fuction为核心代码,下面的全部是封装的方法,可直接复制使用
/**
*生成签名算法
*/
function getSign($array)
{
$pay_key = "12ed7bd47d66f4ef7865f79b2194a94b";
unset($array['sign']);
ksort($array);
$stringA = urldecode(http_build_query($array));
$stringSignTemp="$stringA&key=".$pay_key;
return strtoupper(md5($stringSignTemp));
}
/**
*生成不重复的字符串
*@param $len 字符串长度
*@return 随机字符串
*/
function rand2($len)
{
$chars='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
$string=time();
for(;$len>=1;$len--)
{
$position=rand()%strlen($chars);
$position2=rand()%strlen($string);
$string=substr_replace($string,substr($chars,$position,1),$position2,0);
}
return $string;
}
/**
* 生成签名, $KEY就是支付key
* @return 签名
*/
function MakeSign( $params,$KEY){
//签名步骤一:按字典序排序数组参数
ksort($params);
$string = $this->ToUrlParams($params); //参数进行拼接key=value&k=v
//签名步骤二:在string后加入KEY
$string = $string . "&key=".$KEY;
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
function ToUrlParams( $params ){
$string = '';
if( !empty($params) ){
$array = array();
foreach( $params as $key => $value ){
$array[] = $key.'='.$value;
}
$string = implode("&",$array);
}
return $string;
}
function xml2array($xml){
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $vals, $index);
xml_parser_free($p);
$data = "";
foreach ($index as $key=>$value) {
if($key == 'xml' || $key == 'XML') continue;
$tag = $vals[$value[0]]['tag'];
$value = $vals[$value[0]]['value'];
$data[$tag] = $value;
}
return $data;
}
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;
}