I haven't updated my blog for a long time. Recently, I met wechat payment for my project. I need to sort out the demand. I need to adjust wechat payment for an activity page!
Application framework THINKPHP5.1
Note: for wechat payment, if it is the h5 page, you need to obtain the code in a silent login state, so as to ensure that the parameter openid of the payment call is normal. The hole here has been filled for a long time. After the h5 user of the wechat browser enters the mobile number and logs in, the cookie information is saved on the page. Sometimes, the obtained openid will not be updated, resulting in "order account and payment" Account number is inconsistent, please check ";
The refresh page of wechat browser is executed with jq: window.location.href = location.href+'?time='+((new Date()).getTime());
Direct up code: front end
function get_form(){
var price1 =$(".get_price1").val();
var price2 =$(".get_price2").val();
var price3 =$(".get_price3").val();
var price4 =$(".get_price4").val();
var pid =$(".pid").val();
var username =$(".username").val();
var mobile =$(".mobile").val();
var address =$(".address").val();
if(!username && !mobile && !address){ layer.alert('Consignee information cannot be empty'); return false; } $.post("home/get_from",//Get from is the logic of background payment request {"price1":price1,"price2":price2,"price3":price3,"price4":price4,"username":username,"mobile":mobile,"address":address,"pid":pid},function(apiConfig){ console.log(apiConfig); var ua = navigator.userAgent.toLowerCase();//Whether the object for obtaining judgment is wechat internal or external if (ua.match(/MicroMessenger/i) == "micromessenger") { //inside WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId":apiConfig.appId, //The name of the public is imported from merchants. "timeStamp":apiConfig.timeStamp, //Time stamp, seconds since 1970 "nonceStr":apiConfig.nonceStr, //Random strings "package":apiConfig.package, "signType":apiConfig.signType, //Wechat signature method: "paySign":apiConfig.paySign //WeChat signature }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ){ window.location.href ="Method path" } }); if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } }else{ onBridgeReady(); } }else{ //external var url="Payment successful jump"; window.location.href =apiConfig.mweb_url+"&redirect_url="+url; } }); }
Back end code:
Reset the route through tp5 redirect during silent login request page
Go to the page again to find out if there is openid
$sa = Cookie::get('kj_phone');
$uid =$sa['id ']; / / user ID
$userAgent = $_SERVER['HTTP_USER_AGENT']; / / judgement is public number payment or external web site payment?
If (strpos ($userAgent,'MicroMessenger')) {/ / public number payment
$uid =$sa['id ']; / / user ID
$open_id= Cache::get($uid);
// print_r($open_id);
if(empty($open_id)){
$this->redirect("Https://open.weixin.qq.com/connect/oauth2/authorize? Appid = appid & redirect URI = after entering the page, first get the code through get open method to get openid & response type = code & scope = snsapi base & state = 1 wechat redirect");
} }
Get open method
public function get_open(){
$code1=empty($_GET['code']) ? '' : $_GET['code']; $sa =Cookie::get('kj_phone'); // $appId ='appId '; //$secret ='secret'; $get_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=Appid&secret=secre&code=' . $code1 . '&grant_type=authorization_code'; $json_obj = $this->http_request($get_token_url); $json_obj = json_decode($json_obj,true); $openid = empty($json_obj['openid']) ? "" : $json_obj['openid']; $uid =$sa['id'];//User id Cache::set($uid,$openid,3600); if($code1 == ''){ $this->redirect('Redirect to render page'); } if(!empty($open_id)){ $this->redirect('Redirect to render page'); }else{ $this->redirect('Redirect to render page'); } }
get_from:
public function get_from(){
if(request()->isPost()){
$data =input("post."); / / write logic for the data from the front end
$userAgent = $_SERVER['HTTP_USER_AGENT']; // Is the public number paid or the external web site paid? if (strpos($userAgent, 'MicroMessenger')) { // Public address payment $sa = Cookie::get('kj_phone'); $uid =$sa['id'];//User id $open_id= Cache::get($uid); //print_r($open_id);exit; $return = $this->weixinapp($open_id,$body,$order_id,$price,$attact); return $return; }else{ $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $parameters = array( 'appid' => "Small program ID", //Applet ID 'mch_id' => "Merchant number", //Merchant number 'attach'=>$attact, 'nonce_str' => $this->createNoncestr(), //Random string 'body' =>$body, //Commodity Description 'out_trade_no' =>$order_id,//Merchant order number 'total_fee' => $price * 100, //Total amount unit: minute 'spbill_create_ip' => '111111', //Terminal IP 'notify_url' => 'token url', //Notification address to ensure normal access to the Internet 'trade_type' => 'MWEB'//Transaction type ); //Unified order signature $parameters['sign'] = $this->getSign($parameters); $xmlData = $this->arrayToXml($parameters); $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60)); return $return; } } } }
//Unified single interface
private function weixinapp($openid,$body,$orderId,$price,$attact) {
$unifiedorder = $this->unifiedorder($openid,$body,$orderId,$price,$attact); $parameters = array( 'appId' => "appId", //Applet ID 'timeStamp' => '' . time() . '', //time stamp 'nonceStr' => $this->createNoncestr(), //Random strings 'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //data packet 'signType' => 'MD5'//Signature method ); //autograph $parameters['paySign'] = $this->getSign($parameters); return $parameters; } //Function: generate random string, no longer than 32 bits 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) { //halt($Obj); foreach ($Obj as $k => $v) { $Parameters[$k] = $v; } //Signature step 1: sort parameters in dictionary order ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //Signature step 2: add KEY after string $String = $String . "&key=d18e10ad06222c972499296f1cefa481" ; //Signature step 3: MD5 encryption $String = md5($String); //Step 4: change all characters to uppercase $result_ = strtoupper($String); return $result_; } ///Function: format parameters. Signature process needs to use 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; } //Array to xml private function arrayToXml($arr) { $xml = "<root>"; foreach ($arr as $key => $val) { if (is_array($val)) { $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">"; } else { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } } $xml .= "</root>"; return $xml; } //xml to array private function xmlToArray($xml) { //Prohibit reference to external xml entities libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring), true); return $val; } function http_curl($url){//Pass parameters with curl $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//Turn off ssl authentication curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch,CURLOPT_HEADER, 0); $output = curl_exec($ch); curl_close($ch); return json_decode($output, true); } private static function postXmlCurl($xml, $url, $second = 30) { $ch = curl_init(); //Set timeout 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); //Strict calibration //Set header curl_setopt($ch, CURLOPT_HEADER, FALSE); //The result is expected to be a string and output to the screen curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //post submission method 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); //Run curl $data = curl_exec($ch); //Return result if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); throw new WxPayException("curl Error, error code:$error"); } } //Callback private function unifiedorder($openid,$body,$orderId,$price,$attact) { $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $parameters = array( 'appid' => "appid", //Applet ID 'mch_id' =>"mch_id", //Merchant number 'attach'=>$attact, 'nonce_str' => $this->createNoncestr(), //Random string 'body' => $body, 'out_trade_no'=> $orderId, 'total_fee' => $price * 100, 'spbill_create_ip' => '11111111', //Terminal IP 'notify_url' => Callback, //Notification address to ensure normal access to the Internet 'openid' => $openid, //User id 'trade_type' => 'JSAPI'//Transaction type ); //Unified order signature $parameters['sign'] = $this->getSign($parameters); $xmlData = $this->arrayToXml($parameters); $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60)); return $return; } //Callback public function callback(){ $xml = file_get_contents("php://input"); // Convert XML to array $xml = json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)); $result = json_decode($xml, true); //If successfully returned if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){ $where['order_id']=$result['out_trade_no']; $data_e['states']=2; $ud= db('hc_pr_order')->where($where)->update($data_e); } // Return value to wechat if ($ud) { $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[Signature failed]]></return_msg></xml>'; } return $str; return $result; }