网上查看了不少微信支付程序,大多数是调用不少类,十分繁杂,出错几率很高。因而本身写的尽可能简单一些,代码以下:php
//$appid和$appsecret 两个是在微信公众号设置的帐号密码,记得appsecret要 保存好哦!$mch_id是微信商户id,要和微信开发公众平台绑定的商户id一致(我由于不这个不一致,当时没注意查看了两天代码)前端
protected $appid = 'wx29c65112380c560';
protected $AppSecret = 'f7241b0b8dc21j2sxe4215bc78c24d1';
protected $mch_id = '150335221';json
/**api
*微信下单数组
*@param total_price 下单金额 单位为/元 安全
*@return 这一步返回prepay_id服务器
*@param $id为新订单的id微信
*/微信开发
function wxpay($total_price='',$id=''){app
// header("Content-type:text/xml;charset=utf-8");
if(empty($total_price)){
//加个测试金额
$total_price = 110;
}
$total_price = 0.01;
$openid = $_SESSION['openid'];
if(empty($openid)){
//加个测试的openid
$openid = 'opFig0knA1xDiGFGlZ9hpxq1aIXE';
}
//拼接商品订单号
$body = '测试商品';
$out_trade_no = date("YmdHis") . rand(100, 999);
//更新支付宝订单号到数据表
$this->ORDER->updateById(array('out_trade_no'=>$out_trade_no),
$id);
$noncestr = $this->rand2(10);
$order = [
'appid'=>$this->appid,
'mch_id'=>$this->mch_id,
'openid'=>$openid,
'nonce_str'=>$noncestr,
'body'=>'测试商品',
'out_trade_no'=>$out_trade_no,//商户惟一订单号,可包含字母序
'total_fee'=>(string)$total_price*100,//订单金额,单位/分因此乘以100
'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],
//产生订单号的服务器IP
'notify_url' => \App_Const::Domain_INDEX . 'notice',//接受微信异步通知地址
'trade_type'=>'JSAPI',//交易类型
];
//MD5处理,默认支持MD5
$order['sign'] = $this->getSign($order);
//转换成一维XML格式
$xml = '<xml>';
foreach($order as $k=>$v){
$xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>';
}
$xml.='</xml>';
//这个key是商户平台加密的字符串,在商户平台必定要复制出来保存好,不要写成appsecret,容易混淆
$KEY = '96e79218965eb72c92a549dd5ax112';//加密的字符串
//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, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
//要传送的全部数据
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 );
// if($response['return_code'] == "SUCCESS" && $response['result_code'] == "SUCCESS"){
//根据微信支付返回的结果进行二次签名
//二次签名所需的随机字符串
$order["nonceStr"] = $noncestr;//随机字符串
//二次签名所需的时间戳
$order['timeStamp'] = time()."";
//二次签名剩余参数的补充
$secondSignArray = array(
"appId"=>$order['appid'],
"nonceStr"=>$order['nonceStr'],
//"package"=>"Sign=WXPay",
"package"=>"prepay_id=".$response['prepay_id'],
"signType"=>"MD5",
"timeStamp"=>$order['timeStamp'],
);
$data = $secondSignArray;
$recharge_num = $order["out_trade_no"];
$data['paySign'] = $this->getSign($secondSignArray,$KEY);
$data['prepay_id'] = $response['prepay_id'];
$data['out_trade_no'] = $out_trade_no;
// $output = array('data'=>$data ,'info'=>"success" ,'code'=>"200" ,'order_number'=>$recharge_num);
$msg['status'] = 'success';
//这个参数的data是前端调起微信支付窗口的数据,之因此写到msg里面,是由于咱们公司前端这么要求,平时用单独 把data写出来就能够
$msg['data'] = array(
'timeStamp'=>time(),
'nonceStr'=>$noncestr,
'package'=>"prepay_id=".$response['prepay_id'],
'signType'=>'MD5',
'paySign'=> $data['paySign'],
);
echo json_encode($msg);die();
}
以上方法传输一个金额,一个订单id便可,完成上面的方法调用就算完成了,可是里面用到的封装function我须要列一下,代码以下:
//这些直接复制就能够 了,不须要作任何修改
function rand2($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
//这个是生成sign的方法,直接复制就能够
function getSign($params) {
ksort($params); //将参数数组按照参数名ASCII码从小到大排序
foreach ($params as $key => $item) {
if (!empty($item)) { //剔除参数值为空的参数
$newArr[] = $key.'='.$item; // 整合新的参数数组
}
}
$stringA = implode("&", $newArr); //使用 & 符号链接参数
$stringSignTemp = $stringA."&key="."96e79218965eb72c92a549d222a330112"; //拼接key
// key是在商户平台API安全里本身设置的
$stringSignTemp = MD5($stringSignTemp); //将字符串进行MD5加密
$sign = strtoupper($stringSignTemp); //将全部字符转换为大写
return $sign;
}
以上微信下单的方法,记得打印prepay_id,这个值很是关键,若是没有的话,即便调用返回值成功,下单也是没成功的。上面代码复制完了,数据返回给前端,前端调用支付窗口,而后付钱,微信会根据上面的回调地址返回成功或者失败。按照时间戳生成的那个订单号,也会在结果里返回,能够搞个 惟一的订单号做为标识,用来更新订单id。回调方法以下:
/**
*支付异步通知
*/
function notice(){
//获取微信的数据流
$testxml = file_get_contents("php://input");
$jsonxml = json_encode(simplexml_load_string($testxml,'SimpleXMLElement', LIBXML_NOCDATA));
$result = json_decode($jsonxml,true);//转换成数组
if($result){
//若是成功了
$out_tarde_no = $result['out_tarde_no'];
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
//支付状态 订单发货状态status 都修改掉
$this->ORDER->update(array('pay_status'=>2,'status'=>2),array('out_trade_no'=>$result['out_trade_no']));
}else{
$this->ORDER->update(array('pay_status'=>3),array('out_trade_no'=>$result['out_trade_no']));
}
}else{
//加一条测试,若是调用接口可是没有成功
$this->ORDER->update(array('pay_status'=>22),array('id'=>10));
}
}
注意回调结果是返回数据流,处理数据流而后根据out_trade_no字段来更新状态的,写到这里,整个微信支付代码就算结束了,谢谢你们观看!