網上查看了不少微信支付程序,大多數是調用不少類,十分繁雜,出錯機率很高。因而本身寫的儘可能簡單一些,代碼以下: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字段來更新狀態的,寫到這裏,整個微信支付代碼就算結束了,謝謝你們觀看!