微信支付的開發文檔 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1php
介紹的是相當簡陋啊。。web
下載sdk和demo: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1ajax
下載好後,放到 component文件夾(我用的是yii2),在sdk文件夾下添加一個 init.phpjson
<?php //init.php 主要是引用lib中的4個文件 require_once dirname(__FILE__).'/lib/WxPay.Api.php'; require_once dirname(__FILE__).'/lib/WxPay.Config.php'; require_once dirname(__FILE__).'/lib/WxPay.Data.php'; require_once dirname(__FILE__).'/lib/WxPay.Exception.php'; require_once dirname(__FILE__).'/lib/WxPay.Notify.php';
支付中須要用到的幾個參數api
app_id, app_secret, MCHID, //商戶號 key
這幾個參數在 「微信公衆平臺開發者設置 」 和 「商戶平臺設置 」 都能獲取到,具體百度。。xcode
先看前臺微信
$("#pay").click(function(){ var pay_way = $("input[type='radio']:checked").val(); if(pay_way == 1){ wap_pay(1) //支付寶 }else if(pay_way == 2){ wechatcallpay() //微信支付 }else if(pay_way == 3){ paypal_pay() //PayPal } });
wechatcallpay(),我是通過 ajax 獲取後臺數據yii2
//wechat 支付 function wechatcallpay() { $.ajax({ type: 'POST', url: '/order/wechatpay', //獲取後臺中的數據 data:"_csrf="+_csrf+"&ssid="+ssid, dataType: 'json', success: function(data){ jsApiParamenters = data if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } }else{ jsApiCall(); } } }); } function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', jsApiParamenters, function(res){ // WeixinJSBridge.log(res.err_msg); // alert(res.err_code+res.err_desc+res.err_msg); if(res.err_msg == "get_brand_wcpay_request:ok" ) { //跳轉到[成功界面] window.location.href = "<?php echo Url::to('/order/success')?>"; } else if(res.err_msg == "get_brand_wcpay_request:cancel"){ //跳轉到[取消界面] window.location.href = "<?php echo Url::to('/order/cancel')?>"; } else { //跳轉到「失敗界面」 window.location.href = "<?php echo Url::to('/order/cancel')?>"; } } ); }
再看看 /order/wechatpaycookie
public function actionWechatpay() { if(Yii::$app->request->isPost) { $ssid = Yii::$app->request->post('ssid'); $online_order = OnlineOrder::find()->where('order_code = :ssid',[':ssid'=>$ssid])->one(); $data = OnlineOrder::findOrderDetail($online_order); $rate = Helper::rate(); //第三方 獲取匯率 $money = ceil($data['total_money'] * $rate * 100); //取整,微信支付已分爲單位,並且不能有小數 $order_number = $data['order_number']; $cookies = Yii::$app->request->cookies; $wx_code = $cookies->getValue('wx_code'); //通過cookies獲取wx_code,獲取方法下面有講 $wx_app_id = Yii::$app->params['wechat']['wx_app_id']; $wx_app_secret = Yii::$app->params['wechat']['wx_app_secret']; $open_id = WechatPay::getOpenid($wx_app_id, $wx_app_secret, $wx_code); //獲取方法下面講 $body = "商品簡述"; $notify_url = Yii::$app->params['wechat']['notify_url']; //回調uRL,支付成功後微信會調用這個接口 $jsApiParams = Helper::getjsApiParams($open_id,$body,$ssid,$money,$order_number,$notify_url); //下面講 echo $jsApiParams; } else { echo 0; } }
首先是wx_code的獲取,app
/** * 判斷是否在微信客戶端打開連接 * 若是是就跳轉到微信code的重定向url地址 * 若是不是就跳到支付寶支付界面 */ public function actionGetcode() { $isWechat = Helper::isWechatBrowser(); //下面有講到if($isWechat){ $url = Helper::GetWxCodeUrl(); //下面講 header("Location: $url"); exit(); } else { $this->redirect(['order/payment']); } }
/** * 經過微信重定向url獲取code, * 而且把code設置爲cookie */ public function actionGetwxcode() { $code = Yii::$app->request->get('code'); //把wx_code做爲cookies保存if(!empty($code)){ $cookies = Yii::$app->response->cookies; $cookies->add(new \yii\web\Cookie([ 'name' => 'wx_code', 'value' => $code, 'expire'=>time()+3600, ])); } $this->redirect(['/order/payment']); }
新建一個 WechatPay.php,主要是獲取 code 和openid
<?php
namespace frontend\components; class WechatPay { /** * 獲取微信公衆號受權用戶惟一標識 * @param $app_id 微信公衆號應用惟一標識 * @param $app_secret 微信公衆號應用密鑰(注意保密) * @param $code 受權code, 經過調用WxpubOAuth::createOauthUrlForCode來獲取 * @return openid 微信公衆號受權用戶惟一標識, 可用於微信網頁內支付 */ public static function getOpenid($app_id, $app_secret, $code) { $url = self::_createOauthUrlForOpenid($app_id, $app_secret, $code); $res = self::_getRequest($url); $data = json_decode($res, true); return $data['openid']; } /** * 用於獲取受權code的URL地址,此地址用於用戶身份鑑權,獲取用戶身份信息,同時重定向到$redirect_url * @param $app_id 微信公衆號應用惟一標識 * @param $redirect_url 受權後重定向的回調連接地址,重定向後此地址將帶有受權code參數, * 該地址的域名需在微信公衆號平臺上進行設置, * 步驟爲:登錄微信公衆號平臺 => 開發者中心 => 網頁受權獲取用戶基本信息 => 修改 * @param bool $more_info FALSE 不彈出受權頁面,直接跳轉,這個只能拿到用戶openid * TRUE 彈出受權頁面,這個能夠經過 openid 拿到暱稱、性別、所在地, * @return string 用於獲取受權code的URL地址 */ public static function createOauthUrlForCode($app_id, $redirect_url, $more_info = false) { $urlObj = array(); $urlObj['appid'] = $app_id; $urlObj['redirect_uri'] = $redirect_url; $urlObj['response_type'] = 'code'; $urlObj['scope'] = $more_info ? 'snsapi_userinfo' : 'snsapi_base'; $urlObj['state'] = "#state"; //這個參數會原封不動地傳回來 $queryStr = http_build_query($urlObj); return 'https://open.weixin.qq.com/connect/oauth2/authorize?' . $queryStr; } /** * 獲取openid的URL地址 * @param $app_id 微信公衆號應用惟一標識 * @param $app_secret 微信公衆號應用密鑰(注意保密) * @param $code 受權code, 經過調用WxpubOAuth::createOauthUrlForCode來獲取 * @return string 獲取openid的URL地址 */ private static function _createOauthUrlForOpenid($app_id, $app_secret, $code) { $urlObj = array(); $urlObj['appid'] = $app_id; $urlObj['secret'] = $app_secret; $urlObj['code'] = $code; $urlObj['grant_type'] = 'authorization_code'; $queryStr = http_build_query($urlObj); return 'https://api.weixin.qq.com/sns/oauth2/access_token?' . $queryStr; } /** * GET 請求 */ private static function _getRequest($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE); curl_setopt($ch, CURLOPT_HEADER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); $res = curl_exec($ch); curl_close($ch); return $res; } public static function getSign($params, $key){ ksort($params, SORT_STRING); $unSignParaString = self::formatQueryParaMap($params, false); $signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); return $signStr; } protected static function formatQueryParaMap($paraMap, $urlEncode = false){ $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v){ if (null != $v && "null" != $v) { if ($urlEncode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } } $reqPar = ''; if (strlen($buff)>0) { $reqPar = substr($buff, 0, strlen($buff) - 1); } return $reqPar; } }
Helper.php
//首先引入 init.php require_once dirname(dirname(__FILE__)).'/components/WxpayAPI/init.php'; /** * 判斷是否微信打開 * @return boolean */ public static function isWechatBrowser() { if (strpos($_SERVER['HTTP_USER_AGENT'],'MicroMessenger') !== false ) { return true; } return false; } /** * 獲取微信code的重定向前的url * @return string */ public static function GetWxCodeUrl() { $wx_app_id = Yii::$app->params['wechat']['wx_app_id']; $redirect_url = Yii::$app->params['wechat']['redirect_url'];//這個就是前面 微信重定向獲取code的ur(/order/getwxcode ) $code_url = WechatPay::createOauthUrlForCode($wx_app_id, $redirect_url); return $code_url; } /** * wechat支付 獲取jsapi參數 */ public static function getjsApiParams($openId,$body,$attach,$money,$order_number,$notify_url,$trade_type="JSAPI") { $input = new \WxPayUnifiedOrder(); $input->SetBody($body); $input->SetAttach($attach); $input->SetOut_trade_no($order_number); $input->SetTotal_fee($money); $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); $input->SetGoods_tag("商品"); $input->SetNotify_url($notify_url); $input->SetTrade_type($trade_type); $input->SetOpenid($openId); $input->setDetail("商品簡介"); $order = \WxPayApi::unifiedOrder($input); //這個函數在 微信sdk中的 ..\lib\WxPay.Api.php $jsApiParameters = \WxPayApi::GetJsApiParameters($order);//這個函數在 微信sdk中的..\lib\WxPay.Api.php return $jsApiParameters; }
接通之後,還須要在 「微信公衆平臺」和 「商戶平臺」設置 授權url,否則是訪問不了微信的接口的,具體百度。。。
「微信回調 Notify_url」
能夠完成支付了,還有就是 回調地址的處理,這個地址是在 上面 actionWechaypay() 中設置的,當支付成功後,微信就會調用
class CallbackController extends BaseController { public $enableCsrfValidation = false; //這個要關閉,否則接收不到數據 public function actionWechat() { $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); if ($postObj === false) { die('parse xml error'); } if ($postObj->return_code != 'SUCCESS') { die("error_code: ".$postObj->err_code.",msg: ".$postObj->return_msg); } $key = Yii::$app->params['wechat']['wx_key']; //驗證簽名 $wechat = new WechatPay(); //這個就是上面的WechatPay.php中的內容 $arr = (array)$postObj; unset($arr['sign']); if($wechat::getSign($arr,$key) != $postObj->sign) { die("簽名錯誤"); }
//之後的邏輯,就是 修改訂單狀態。。。
return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; } }