<?php
namespace App\Http\Controllers\Move;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
//移动端微信扫码支付
class Move_payment extends Controller
{
public function move_payment()
{
// 导入微信支付sdk
$wxpay=new Weixinpay();
// 获取jssdk需要用到的数据
// $datat=$wxpay->getParameters(111); //微信支付
// // 扫码支付
$order=array(
'body'=>'商品描述(需要根据自己的业务修改)',// 商品描述(需要根据自己的业务修改)
'total_fee'=>0.01*100,// 订单金额 以(分)为单位(需要根据自己的业务修改)
'out_trade_no'=>time(),// 订单号(需要根据自己的业务修改)发起支付时订单号处于使用中,如果二次修改金额需要修改订单号
'product_id'=>time(),// 商品id(需要根据自己的业务修改)
'trade_type'=>'NATIVE',// JSAPI公众号支付
'openid'=>$openid// 获取到的openid
);
$datat=$wxpay->pay($order);
var_dump($datat);exit;
$data = array(
'datas'=>json_encode($datat)
);
return view('web_pc.live_info.plyr',$data);
}
//移动端微信支付回调地址 必须是post的
public function move_wxpay_notify()
{
$testxml = file_get_contents("php://input");
$jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
$result = json_decode($jsonxml, true);//转成数组,
if($result){
//如果成功返回了
$out_trade_no = $result['out_trade_no'];
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
// //执行业务逻辑改变订单状态等操作
// //查询创建订单表 where("out_trade_no='".$out_trade_no."' and status=1") status为1表示待支付状态 1 待支付
// //查询出来有该订单 就改变支付状态 status=2 2表示支付成功
$data = array(
'addtime' =>date('Y-m-d H:i:s'),
'data' =>$jsonxml
);
Db::table('wxcallback')->insert($data);
// //先判断订单状态是否已经改变
// $orderData = M("wxpay_order")->where("w_out_trade_no='".$result['out_trade_no']."' and w_status=1")->find();
// if(!empty($orderData)){
// //支付成功改变支付状态
// $arr = array(
// 'w_id'=>$orderData['w_id'],
// 'w_openid'=>$result['openid'],
// 'w_transaction_id'=>$result['transaction_id'],
// 'w_time_end'=>$result['time_end'],
// 'w_times_end'=>$result['time_end'],
// 'w_total_fee'=>$result['total_fee']/100,
// 'w_status'=>2,//支付成功 1 待支付 2支付成功 3 支付失败
// );
// M('wxpay_order')->save($arr);
// //操作积分
// $uid = $orderData['w_mId'];
// //对该人增加$result['total_fee']积分
// $zz_grade = M('grade');
// $g_Integral = $zz_grade->where("g_mId=".$uid)->getField('g_Integral');
// $zz_grade->g_Integral = $g_Integral + intval($result['total_fee']/100);
// //更新积分
// $giddd = $zz_grade->where("g_mId=".$uid)->save();
// //操作积分日志表
// $zz_grade_log = M('grade_log');
// $zz_grade_log->g_gContent = '充值'.intval($result['total_fee']/100).'积分';
// $zz_grade_log->g_mId = $uid;//邀请者会员id
// $zz_grade_log->g_gNum = intval($result['total_fee']/100);//充值积分
// $zz_grade_log->g_gDate = date('Y-m-d');//注册日期
// $zz_grade_log->g_gTime = date('Y-m-d H:i:s');//注册时间
// //写入数据库
// $liddd = $zz_grade_log->add();
// }
}
}
}
}
// error_reporting(E_ALL);
// ini_set('display_errors', '1');
// 定义时区
ini_set('date.timezone','Asia/Shanghai');
class Weixinpay {
// 定义配置项
private $config=array(
'APPID' => 'wxffbc0e6245dcd422b', // 微信支付APPID
'MCHID' => '157579161112', // 微信支付MCHID 商户收款账号
'KEY' => 'yunlive1234567893asdfghjklqwertyu', // 微信支付KEY
'APPSECRET' => '998e91fa7fe9f5e443257ce2cb3d91cdf', //公众帐号secert
'NOTIFY_URL' => 'https://www.xxxxx.com/move_wxpay_notify', // 接收支付状态的连接 改成自己的域名
);
// 构造函数
// public function __construct(){
// // 如果是在thinkphp中 那么需要补全/Application/Common/Conf/config.php中的配置
// // 如果不是在thinkphp框架中使用;那么注释掉下面一行代码;直接补全 private $config 即可
// $this->config=C('WEIXINPAY_CONFIG');
// }
/**
* 统一下单
* @param array $order 订单 必须包含支付所需要的参数 body(产品描述)、total_fee(订单金额)、out_trade_no(订单号)、product_id(产品id)、trade_type(类型:JSAPI,NATIVE,APP)
*/
public function unifiedOrder($order){
// 获取配置项
$weixinpay_config=$this->config;
$config=array(
'appid'=>$weixinpay_config['APPID'],
'mch_id'=>$weixinpay_config['MCHID'],
'nonce_str'=>$this->nonce_str(),// //随机32位字符串
'spbill_create_ip'=>$this->get_real_ip(), //微信支付获取用户IP
'notify_url'=>$weixinpay_config['NOTIFY_URL']
);
// 合并配置数据和订单数据
$data=array_merge($order,$config);
// 生成签名
$sign=$this->makeSign($data);
$data['sign']=$sign;
$xml=$this->toXml($data);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//接收xml数据的文件
$header[] = "Content-type: text/xml";//定义content-type为xml,注意是数组
$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 兼容本地没有指定curl.cainfo路径的错误
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$response = curl_exec($ch);
if(curl_errno($ch)){
// 显示报错信息;终止继续执行
die(curl_error($ch));
}
curl_close($ch);
$result=$this->toArray($response);
// 显示错误信息
if ($result['return_code']=='FAIL') {
die($result['return_msg']);
}
$result['sign']=$sign;
$result['nonce_str']='test';
return $result;
}
//获取用户ip地址
private function get_real_ip(){
if(getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknow")){
$ip = getenv("HTTP_CLIENT_IP");
}else if(getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknow")){
$ip = getenv("HTTP_X_FORWARDED_FOR");
}else if(getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknow")){
$ip = getenv("REMOTE_ADDR");
}else if(isset($_SERVER["REMOTE_ADDR"]) && $_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"],"unknow")){
$ip = $_SERVER["REMOTE_ADDR"];
}else{
$ip = "unknow";
}
return $ip;
}
//随机32位字符串
private function nonce_str(){
$result = '';
$str = 'mengyilingjian890106zhuimeng8899';
for ($i=0;$i<32;$i++){
$result .= $str[rand(0,48)];
}
return $result;
}
/**
* 验证
* @return array 返回数组格式的notify数据
*/
public function notify(){
// 获取xml
$xml=file_get_contents('php://input', 'r');
// 转成php数组
$data=$this->toArray($xml);
// 保存原sign
$data_sign=$data['sign'];
// sign不参与签名
unset($data['sign']);
$sign=$this->makeSign($data);
// 判断签名是否正确 判断支付状态
if ($sign===$data_sign && $data['return_code']=='SUCCESS' && $data['result_code']=='SUCCESS') {
$result=$data;
}else{
$result=false;
}
// 返回状态给微信服务器
if ($result) {
$str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
}else{
$str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
}
echo $str;
return $result;
}
/**
* 输出xml字符
* @throws WxPayException
**/
public function toXml($data){
if(!is_array($data) || count($data) <= 0){
throw new WxPayException("数组数据异常!");
}
$xml = "<xml>";
foreach ($data as $key=>$val){
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
/**
* 生成签名
* @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
*/
public function makeSign($data){
// 去空
$data=array_filter($data);
//签名步骤一:按字典序排序参数
ksort($data);
$string_a=http_build_query($data);
$string_a=urldecode($string_a);
//签名步骤二:在string后加入KEY
$config=$this->config;
$string_sign_temp=$string_a."&key=".$config['KEY'];
//签名步骤三:MD5加密
$sign = md5($string_sign_temp);
// 签名步骤四:所有字符转为大写
$result=strtoupper($sign);
return $result;
}
/**
* 将xml转为array
* @param string $xml xml字符串
* @return array 转换得到的数组
*/
public function toArray($xml){
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $result;
}
/**
* 获取jssdk需要用到的数据
* @return array jssdk需要用到的数据
*/
// public function getParameters($order_sn,$remark,$money){
public function getParameters(){
// 获取配置项
$config=$this->config;
// var_dump($config);exit;
// 如果没有get参数没有code;则重定向去获取openid;
// echo 2;die;
// if (!isset($_GET['code'])) {
// // 获取订单号
// $out_trade_no=$order_sn;
// // 返回的url
// $redirect_uri=U('Mobile/Alipay/pay_callback','','',true);
// $redirect_uri=urlencode($redirect_uri);
// $url='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$config['APPID'].'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsapi_base&state='.$out_trade_no.'#wechat_redirect';
// // echo $url;die;
// redirect($url);
// }else{
// 如果有code参数;则表示获取到openid
// $code=I('get.code');
// $code=I('get.code');
// $out_trade_no=$_REQUEST['state'];
// $orders = M('vip_order')->where(array('trade_no'=>$out_trade_no))->find();
// print_r($orders);die;
// echo $code;die;
// 取出订单号
// 组合获取prepay_id的url
// $url='https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$config['APPID'].'&secret='.$config['APPSECRET'].'&code='.$code.'&grant_type=authorization_code';
// // curl获取prepay_id
// $result=$this->curl_get_contents($url);
// $result=json_decode($result,true);
// $openid=$result['openid'];
$openid='oEG8_w2-pSuN4Xh3xShj9lD3V1pM';
// 订单数据 请根据订单号out_trade_no 从数据库中查出实际的body、total_fee、out_trade_no、product_id
// $order=array(
// 'body'=>$orders['remark'],// 商品描述(需要根据自己的业务修改)
// 'total_fee'=>$orders['total_fee']*100,// 订单金额 以(分)为单位(需要根据自己的业务修改)
// 'out_trade_no'=>$orders['trade_no'],// 订单号(需要根据自己的业务修改)
// 'product_id'=>$orders['trade_no'],// 商品id(需要根据自己的业务修改)
// 'trade_type'=>'JSAPI',// JSAPI公众号支付
// 'openid'=>$openid// 获取到的openid
// );
$order=array(
'body'=>'商品描述(需要根据自己的业务修改)',// 商品描述(需要根据自己的业务修改)
'total_fee'=>0.01*100,// 订单金额 以(分)为单位(需要根据自己的业务修改)
'out_trade_no'=>time(),// 订单号(需要根据自己的业务修改)发起支付时订单号处于使用中,如果二次修改金额需要修改订单号
'product_id'=>time(),// 商品id(需要根据自己的业务修改)
'trade_type'=>'JSAPI',// JSAPI公众号支付
'openid'=>$openid// 获取到的openid
);
// 统一下单 获取prepay_id
$unified_order=$this->unifiedOrder($order);
// 获取当前时间戳
$time=time();
// 组合jssdk需要用到的数据
$data=array(
'appId'=>$config['APPID'], //appid
'timeStamp'=>strval($time), //时间戳
'nonceStr'=>$unified_order['nonce_str'],// 随机字符串
'package'=>'prepay_id='.$unified_order['prepay_id'],// 预支付交易会话标识
'signType'=>'MD5'//加密方式
);
// 生成签名
$data['paySign']=$this->makeSign($data);
// print_r($data);die;
return $data;
// }
}
/**
* 生成支付二维码
* @param array $order 订单 必须包含支付所需要的参数 body(产品描述)、total_fee(订单金额)、out_trade_no(订单号)、product_id(产品id)、trade_type(类型:JSAPI,NATIVE,APP)
*/
public function pay($order){
$result=$this->unifiedOrder($order);
$decodeurl=urldecode($result['code_url']);
var_dump($decodeurl);exit; //把这个链接变为二维码进行手机扫码支付
qrcode($decodeurl);
}
/**
* curl 请求http
*/
public function curl_get_contents($url){
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url); //设置访问的url地址
// curl_setopt($ch,CURLOPT_HEADER,1); //是否显示头部信息
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //设置超时
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); //用户访问代理 User-Agent
curl_setopt($ch, CURLOPT_REFERER,$_SERVER['HTTP_HOST']); //设置 referer
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1); //跟踪301
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回结果
$r=curl_exec($ch);
curl_close($ch);
return $r;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>支付</title>
</head>
<script src="/new_wap/js/vendors/jquery-1.12.4.min.js"></script>
<body style="text-align: center;">
<button οnclick="getOrder()">支付22</button>
<input type="text" id="datas" value="{{$datas}}">
<!-- <jquery /> -->
<script>
function onBridgeReady(){
var data=$('#datas').val();
var result=JSON.parse(data);
console.log(data)
WeixinJSBridge.invoke(
'getBrandWCPayRequest',{
"appId":result.appId, //公众号名称,由商户传入
"timeStamp":result.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr":result.nonceStr, //随机串
"package":result.package,
"signType":"MD5", //微信签名方式:
"paySign":result.paySign //微信签名
} ,
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
alert('err_msg',res);
// window.location.href='http://v3.mpwdl.com/index.php/Mobile/User/index';
// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
}else{
alert(res.err_code+res.err_desc+res.err_msg); // 显示错误信息
window.history.go(-1);
}
}
);
}
function getOrder() {
var data=$('#datas').val();
var result=JSON.parse(data);
console.log('22',result.appId);
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}
}
</script>
</body>
</html>
d前端调用后端的数据进行支付
重点
1.回调的路由必须是post
//微信支付功能
Route::post('pc_payment', 'WebNew\Pc_payment@pc_payment'); //pc端微信扫码支付
// Route::match(['get','post'],'pc_payment','WebNew\Pc_payment@pc_payment');
Route::get('move_payment', 'Move\Move_payment@move_payment'); //移动端微信支付
Route::post('move_wxpay_notify', 'Move\Move_payment@move_wxpay_notify'); //移动端微信支付回调地址 必须是post的
2.laravel框架必须要把这个路由加入到这文件,回调才可以访问
3,回调地址写法
在商户平台写入顶级域名且不一定是.php的后缀
https://www.x x x x.com/move_wxpay_notify
以上代码在laravel5.5直接运行