php 微信小程序支付 php
直接貼代碼:前端
前端測試按鈕wxml:json
<view class="container"> <text class="name">當前選擇:《參加活動》 ¥0.01</text> <view class="pay" bindtap="onTap">確認支付</view> </view>
wxss:小程序
.container { padding: 50rpx; } .pay { margin-top: 30rpx; color: #fff; background-color: #1fb922; }
js:後端
Page({ /** * 頁面的初始數據 */ onTap () { console.log('6666'); let _self = this; _self._togglePay(); //發起網絡請求 wx.request({ url: '付款url', method: "POST", data: { openid: '', money:0.01 }, header: { "content-type": "application/x-www-form-urlencoded" }, success(res) { var params = res.data.data; wx.requestPayment({ 'timeStamp': String(params['timeStamp']), 'nonceStr': params['nonceStr'], 'package': params['package'], 'signType': params['signType'], 'paySign': params['paySign'], 'success': function (res) { wx.showToast({ title: '支付成功', icon: 'success', duration: 2000 }) _self._togglePay(); }, 'fail': function (res) { wx.showToast({ title: '支付失敗', icon: 'none', duration: 2000 }) _self._togglePay(); }, }) } }) }, _togglePay() { this.setData({ pay: !this.data.pay }); } })
後端PHP代碼:微信小程序
首先是公共函數,處理數據用的:api
// curl請求方法封裝 private 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_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20); curl_setopt($ch, CURLOPT_TIMEOUT, 40); set_time_limit(0); //運行curl $data = curl_exec($ch); //返回結果 if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); throw new Exception("curl出錯,錯誤碼:$error"); } } //數組轉換成xml private function arrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key => $val) { if (is_array($val)) { $xml .= "<" . $key . ">" . $this->arrayToXml($val) . "</" . $key . ">"; } else { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } } $xml .= "</xml>"; return $xml; } //xml轉換成數組 private function xmlToArray($xml) { //禁止引用外部xml實體 libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring), true); return $val; } //做用:產生隨機字符串,不長於32位 private function createNoncestr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str = ""; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } //做用:生成簽名 private function getSign($Obj) { foreach ($Obj as $k => $v) { $Parameters[$k] = $v; } //簽名步驟一:按字典序排序參數 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //簽名步驟二:在string後加入KEY $String = $String . "&key=" . $this->key; //簽名步驟三:MD5加密 $String = md5($String); //簽名步驟四:全部字符轉爲大寫 $result_ = strtoupper($String); return $result_; } // 做用:格式化參數,簽名過程須要使用 private function formatBizQueryParaMap($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if ($urlencode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } $reqPar=''; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff) - 1); } return $reqPar; } /*生成訂單號*/ private function out_trade_no(){ //return date('YmdHis').md5($openid.time().rand(10,99));//32位 return date('YmdHis',time()).time().rand(10,99); }
業務代碼:數組
//統一下單 private function unifiedorder($body,$openid,$pay) { $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; // 這裏的參數順序必定要按下面的,否則可能就一直報商戶號此功能未受權等錯誤 $parameters = array( 'appid' => $this->appid, // 小程序ID 'body' => $body, //支付標題 'mch_id' => $this->mch_id, // 商戶號 'nonce_str' => $this->createNoncestr(), // 隨機字符串 'notify_url' => $this->notify_url, //'https://shop.gdpress.cn/syw_jingzhun/index.php/Api/xiaochengxu/notify_url_api', // 通知地址 確保外網能正常訪問 'openid' => $openid, // 用戶id 'out_trade_no'=> $this->out_trade_no(), // 商戶訂單號 'spbill_create_ip' => Yii::$app->request->userIP, // 終端IP ,這是YII2框架的寫法 'total_fee' => floatval($pay * 100), //支付金額 單位 分 'trade_type' => 'JSAPI' // 交易類型 ); //統一下單簽名 $parameters['sign'] = $this->getSign($parameters); $xmlData = $this->arrayToXml($parameters); $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60)); return $return; } //微信小程序支付接口 調用 public function actionWxpay() { $body='小程序支付測試'; $openid='';//付款者openid $pay='0.01';//支付金額 //統一下單接口 $unifiedorder = $this->unifiedorder($body,$openid,$pay); // 統一下單出錯,參數出錯等緣由 if($unifiedorder['return_code'] == 'FAIL') { return Json::encode(['code'=>400,'msg'=>'支付失敗','data'=>$unifiedorder['return_msg']]); } // 對統一下單返回得參數進行處理 $parameters = array( 'appId' => $this->appid, // 小程序ID 'timeStamp' => '' . time() . '', // 時間戳 'nonceStr' => $this->createNoncestr(), // 隨機串 'package' => 'prepay_id=' . $unifiedorder['prepay_id'], // 數據包 'signType' => 'MD5' // 簽名方式 ); // 小程序發起支付簽名 $parameters['paySign'] = $this->getSign($parameters); return Json::encode(['code'=>200,'msg'=>'支付成功','data'=>$parameters]); }
支付成功回調:服務器
*微信支付的 異步通知 *回調地址*/ public function actionNoticefy() { $xml = file_get_contents("php://input"); //將服務器返回的XML數據轉化爲數組 $data = $this->xmlToArray($xml); // 判斷簽名是否正確 判斷支付狀態 if (($data['return_code'] == 'SUCCESS')) {//支付成功 $result = $data; //獲取服務器返回的數據 $out_trade_no = $data['out_trade_no']; // 訂單單號 $openid = $data['openid']; // 付款人openID $total_fee = floatval(($data['total_fee'])/100); // 付款金額 $transaction_id = $data['transaction_id']; // 微信支付流水號 $time_end = $data['time_end']; // 處理時間 //查找訂單 $order=ActivityOrder::find()->where(['out_trade_no'=>$out_trade_no])->one(); if ($order) {// 訂單存在 $result=true; }else{// 訂單不存在,則建立訂單 $activityOrder=new ActivityOrder(); $activityOrder->out_trade_no=$out_trade_no; $activityOrder->openid=$openid; $activityOrder->activity_id=48; $activityOrder->status=1; $activityOrder->total_fee=$total_fee; $activityOrder->transaction_id=$transaction_id; $activityOrder->time_end=$time_end; $activityOrder->userIP=Yii::$app->request->userIP; $activityOrder->create_time=time(); if ($activityOrder->save()){ $result=true; }else{ $result = false; } } }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>'; } return $str; }
注:本支付基於Yii2框架編寫,若用其餘框架,請自行改掉名稱等Yii2專有函數。微信