首先从小程序端接收订单号、金额等参数,然后后台进行统一下单,把微信支付的订单号返回,在把订单号发送给前台,前台拉起支付,返回参数后更改支付状态。。。
回调
public function notify() {
$wechat=Db::name('wechat')->where('status',1)->find();
//$post = $GLOBALS['HTTP_RAW_POST_DATA'];
$post = file_get_contents("php://input"); //接受POST数据XML个数
// $order_over_test['openid']=$post;
// Db::name('order_over')->insert($order_over_test);
$post_data = $this->xml_to_array($post);
//输出订单号
$order_sn = $post_data['out_trade_no'];
$order_over['order_sn']=$order_sn;
$order_over['money']=$post_data['total_fee'];
$order_over['openid']=$post_data['openid'];
$order_over['time_end']=$post_data['time_end'];
$order_update['status']='1';
// Db::name('order_over')->insert($order_over);
$order_info=Db::name('order')->where('order_id',$order_sn)->find();
if ($post_data['return_code'] == 'SUCCESS') {
//判断证书是否正确
// if ($postSign != $user_sign) {
// Log::write('签名不匹配');
// exit;
// }
if ($order_info['status'] != '1') {
Db::name('order_over')->insert($order_over);
$result=Db::name('order')->where('order_id', $order_sn)->update($order_update);
}
return 'success';
} else {
return 'error';
//$this->error('error!');
}
}
public function xmlToArray($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;
}
public function xml_to_array($xml){
if(!$xml){
return false;
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $data;
}
public static function ToUrlParams($data)
{
$buff = "";
foreach ($data as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
统一下单
public function getwxpay($orderSn,$money)
{
// $orderSn=$orderSn;
$body='广告投放';
//$orderSn='HB14257311281654';
//$money= '1';
$money=$money*100;
$wechat=Db::name('wechat')->where('status',1)->find();
$order_id=$orderSn;
// $money= $money; //充值金额 微信支付单位为分
$appid = $wechat['appid']; //应用APPID
$mch_id =$wechat['mch_id']; //微信支付商户号
$KEY = $wechat['key']; //微信商户API密钥
$out_trade_no = $orderSn ;//平台内部订单号
$nonce_str = $this->rand_code();//随机字符串
// $openid='oM0TH0nyMtlyrP_J8cOL70oLYaCw';
$openid=session('openid');
//获取系统的配置
//$nonce_str = $this->rand_str(12);//随机字符串
$notify_url = "http://**********************t/Wxnotify/notify"; //支付完成回调地址url,不能带参数
$spbill_create_ip = get_client_ip();
$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($money); //总金额 最低为一分钱 必须是整数
$post['trade_type'] = $trade_type;
$sign = $this->MakeSign($post, $KEY); //签名
$this->sign = $sign;
$post_xml = "
$appid
$mch_id
$nonce_str
$body
$notify_url
$openid
$out_trade_no
$spbill_create_ip
{$post["total_fee"]}
$trade_type
$sign
";
//统一下单接口prepay_id
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$xml = $this->http_request($url, $post_xml); //POST方式请求http
$array = $this->xml2array($xml); //将【统一下单】api返回xml数据转换成数组,全要大写
$array['my_sign'] = $sign;
$array['post_xml'] = $post_xml;
$array['source_xml'] = $xml;
if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
$time = time();
$tmp = ''; //临时数组用于签名
$tmp['appId'] = $appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id=' . $array['PREPAY_ID'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time";
// $data['state'] = 1;
$data['timeStamp'] = "$time"; //时间戳
$data['nonceStr'] = $nonce_str; //随机字符串
$data['signType'] = 'MD5'; //签名算法,暂支持 MD5
$data['package'] = 'prepay_id='.$array['PREPAY_ID']; //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = $this->MakeSign($tmp, $KEY); //签名,具体签名方案参见微信公众号支付帮助文档;
$data['prepay_id'] = $array['PREPAY_ID'];
$data['out_trade_no'] = $out_trade_no;
$data['order_id'] = $order_id;
} else {
// $data['statusCode'] = ;
$data['statusMsg'] = "请求错误";
$data['data']['RETURN_CODE'] = $array['RETURN_CODE'];
$data['data']['RETURN_MSG'] = $array['RETURN_MSG'];
}
return $data;
}
public function postXmlCurl($xml,$url,$second = 30){
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
}else{
$error = curl_errno($ch);
curl_close($ch);
echo "curl出错,错误码:$error"."
";
}
}
//生成签名
public 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;
}
/**
* 格式化参数格式化成url参数
*/
public static function ToUrlParams($data)
{
$buff = "";
foreach ($data as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
//发送http请求
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);
//
$zs1 = CMF_ROOT . "cert/apiclient_cert.pem";
$zs2 = CMF_ROOT . "cert/apiclient_key.pem";
// curl_setopt ( $curl, CURLOPT_SSLCERT, $zs1 );
// curl_setopt ( $curl, CURLOPT_SSLKEY, $zs2 );
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLCERT, $zs1);
curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLKEY, $zs2);
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;
}
//获取xml里面数据,转换成array
public 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;
}
//随机字符串
public function rand_code($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
public function ToXml($data=array())
{
if(!is_array($data) || count($data) <= 0)
{
return '数组异常';
}
$xml = "";
foreach ($data as $key=>$val)
{
if (is_numeric($val)){
$xml.="<".$key.">".$val."".$key.">";
}else{
$xml.="<".$key.">".$key.">";
}
}
$xml.=" ";
return $xml;
}
前台页面拉起微信支付
订单支付 {$site_info.site_name|default=''}
核实订单
订单号
{$order_info['order_id']}
金额
{$order_info['money']}¥