Ecshop微信支付JSAPI的介面
阿新 • • 發佈:2018-12-23
話說微信自從和支付寶大戰之後,微信支付被逼得上線了,不然微信瀏覽器裡是無法正常完成支付寶支付的,特別是做過授權登入的網站,如果想用第三方瀏覽器開啟連結去呼叫支付寶支付的話,可能還會出現各種奇葩問題。而且一旦這些問題和錢搭上關係後,處理起來就必須謹慎再謹慎了。
被逼無奈下,加上手機版的微信支付介面,下面給出介面檔案原始碼,其他檔案,例如語言包啊,就自己寫寫吧。
<?php /* 微信支付 */ /* V 1.0 */ /* by tiandi */ /* www.tiandiyoyo.com */ /* 2015.3.23 */ if (!defined('IN_ECTOUCH')) { die('Hacking attempt'); } $payment_lang = ROOT_PATH . 'lang/' .$GLOBALS['_CFG']['lang']. '/payment/wxpay.php'; if (file_exists($payment_lang)) { global $_LANG; include_once($payment_lang); } /* 模組的基本資訊 */ if (isset($set_modules) && $set_modules == TRUE) { $i = isset($modules) ? count($modules) : 0; /* 程式碼 */ $modules[$i]['code'] = basename(__FILE__, '.php'); /* 描述對應的語言項 */ $modules[$i]['desc'] = 'wxpay_desc'; /* 是否支援線上支付 */ $modules[$i]['is_online'] = '1'; /* 作者 */ $modules[$i]['author'] = 'tiandi'; /* 網址 */ $modules[$i]['website'] = 'http://www.tiandiyoyo.com'; /* 版本號 */ $modules[$i]['version'] = '1.0'; /* 配置資訊 */ $modules[$i]['config'] = array( array('name' => 'wxpay_appid', 'type' => 'text', 'value' => ''), array('name' => 'wxpay_mchid', 'type' => 'text', 'value' => ''), array('name' => 'wxpay_apikey', 'type' => 'text', 'value' => '') ); return; } class wxpay { var $para; var $openid; function wxpay() { } function __construct() { } function set_para($key,$value){ $this->para[$key] = $value; } function get_code($order, $payment){ $sql = "SELECT wxid FROM " .$GLOBALS['ecs']->table('users'). " WHERE user_id = ".$_SESSION['user_id']; $wxid = $GLOBALS['db']->getOne($sql); $apikey = $payment['wxpay_apikey']; $appid = $payment['wxpay_appid']; $callback_url = $GLOBALS['ecs']->url() . 'respond.php?code=wxpay'; $ip = getIPaddress(); $timestamp = time(); $noncestr = $this->create_noncestr(); $this->set_para("nonce_str", $noncestr); //隨機字串 $this->set_para("appid", $appid); //公眾號 $this->set_para("mch_id", $payment['wxpay_mchid']); //商戶號 //$this->set_para("device_info", 'WEB'); //終端裝置號(商戶的門店號或裝置ID),注意:PC網頁或公眾號內支付請傳"WEB" $this->set_para("body", $order['order_sn']); //商品或支付單簡要描述 $this->set_para("out_trade_no", $order['order_sn'] . 'O' . $order['log_id']); //商戶訂單號 $this->set_para("total_fee", floor($order['order_amount']*100)); //付款金額,單位分 $this->set_para("spbill_create_ip", $ip); // 終端地址 $this->set_para("notify_url", $callback_url); //非同步通知地址 $this->set_para("trade_type", 'JSAPI'); //交易型別 JSAPI,NATIVE,APP $this->set_para("openid", $wxid); //使用者openid $postxml = $this->create_xml($apikey); $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $response = $this->curl_post_ssl($url, $postxml); $responseObj = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA); //print_r($responseObj); $prepay_id = "prepay_id=".$responseObj->prepay_id; $signkey = getkey($noncestr,$prepay_id,$timestamp,$appid,$apikey); $button = '<div style="text-align:center"><input type="button" onclick="onBridgeReady()" value="' .$GLOBALS['_LANG']['pay_button']. '" class="c-btn3" /></div>'; $js = "<script>function onBridgeReady(){". "WeixinJSBridge.invoke(". "'getBrandWCPayRequest', {". "'appId' : '".$payment['wxpay_appid']."', ". "'timeStamp':'".$timestamp."',". "'nonceStr' : '".$noncestr."',". "'package': '".$prepay_id."',". "'signType' : 'MD5',". "'paySign' : '".$signkey."'". "},". "function(res){ ". "if(res.err_msg == 'get_brand_wcpay_request:ok' ) ". "{". "alert('支付成功!');". "window.location.href='user.php?act=order_list';". "}". "else {". "alert('支付失敗!');". "} });} ". " </script>"; return $button.$js; } function respond($postStr) { $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; $responseObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); $json = json_encode($responseObj); $res = json_decode($json, true); if($this->check_respond_date($res)) { $out_trade_no = $res['out_trade_no']; $out_trade_no = explode('O', $out_trade_no); $order_sn = $out_trade_no[0];//訂單號 $log_id = $out_trade_no[1];//訂單號log_id if($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS') { // by tiandi 改變子訂單狀態 sub_order_paid($order_sn, $log_id, 2); /* 改變訂單狀態 */ order_paid($order_sn, $log_id, 2); echo "success"; } else { echo "fail"; } } else echo "fail"; } function check_respond_date($res) { $sql = "SELECT pay_config FROM " .$GLOBALS['ecs']->table('touch_payment'). " WHERE pay_code = '".$res['code']."'"; $result = $GLOBALS['db']->getOne($sql); $config = $this->unserialize_config($result); $apikey = $config['wxpay_apikey']; ksort($res); $tempsign = ""; foreach ($res as $k => $v){ if (null != $v && "null" != $v && "sign" != $k && "code" != $k) { $tempsign .= $k . "=" . $v . "&"; } } $tempsign = substr($tempsign, 0, strlen($tempsign)-1); //去掉最後的& $tempsign .="&key=". $apikey; //拼接APIKEY $sign = strtoupper(md5($tempsign)); if($sign == $res['sign']) { return true; } else { return false; } } function unserialize_config($cfg){ if (is_string($cfg) && ($arr = unserialize($cfg)) !== false) { $config = array(); foreach ($arr AS $key => $val) { $config[$val['name']] = $val['value']; } return $config; } else { return false; } } function create_noncestr( $length = 24 ) { $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } function check_sign_para(){ if($this->para["appid"] == null || // $this->para["device_info"] == null || $this->para["mch_id"] == null || $this->para["nonce_str"] == null || $this->para["body"] == null || $this->para["out_trade_no"] == null || $this->para["total_fee"] == null || $this->para["spbill_create_ip"] == null || $this->para["notify_url"] == null || $this->para["trade_type"] == null || $this->para["openid"] == null ) { return false; } return true; } function create_sign($apikey){ if($this->check_sign_para() == false) { echo "簽名引數錯誤!"; } ksort($this->para); $tempsign = ""; foreach ($this->para as $k => $v){ if (null != $v && "null" != $v && "sign" != $k) { $tempsign .= $k . "=" . $v . "&"; } } $tempsign = substr($tempsign, 0, strlen($tempsign)-1); //去掉最後的& $tempsign .="&key=". $apikey; //拼接APIKEY return strtoupper(md5($tempsign)); } function create_xml($apikey){ $this->set_para('sign', $this->create_sign($apikey)); return $this->ArrayToXml($this->para); } function ArrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key=>$val) { if (is_numeric($val)) { $xml.="<".$key.">".$val."</".$key.">"; } else $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } $xml.= "</xml>"; return $xml; } function curl_post_ssl($url, $vars, $second=30) { $ch = curl_init(); //超時時間 curl_setopt($ch,CURLOPT_TIMEOUT,$second); curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml')); curl_setopt($ch,CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_POSTFIELDS,$vars); $data = curl_exec($ch); if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); return false; } } } function getIPaddress() { $IPaddress=''; if (isset($_SERVER)){ if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])){ $IPaddress = $_SERVER["HTTP_X_FORWARDED_FOR"]; } else if (isset($_SERVER["HTTP_CLIENT_IP"])) { $IPaddress = $_SERVER["HTTP_CLIENT_IP"]; } else { $IPaddress = $_SERVER["REMOTE_ADDR"]; } } else { if (getenv("HTTP_X_FORWARDED_FOR")){ $IPaddress = getenv("HTTP_X_FORWARDED_FOR"); } else if (getenv("HTTP_CLIENT_IP")) { $IPaddress = getenv("HTTP_CLIENT_IP"); } else { $IPaddress = getenv("REMOTE_ADDR"); } } return $IPaddress; } function getkey($noncestr,$prepay_id,$timestamp,$appid,$apikey) { $tempsign = "appId=".$appid."&nonceStr=".$noncestr."&package=".$prepay_id."&signType=MD5&timeStamp=".$timestamp."&key=".$apikey; return strtoupper(md5($tempsign)); }