微信小程序PHP微信支付

2018-03-01 11:12:39来源:oschina作者:孔先森人点击

分享

PHP之小程序支付


小程序支付,其实还是挺简单的, 把逻辑搞清楚,


前端代码看文档


https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=5

前端需要的参数,先调用 “ 预支付请求接口API” 生成订单返回参数,即可调起微信支付


在预支付订单API的时候,首先是统一下单的签名,对应好签名所需要的参数,统一下订单成功后,小程序还需签名, 小程序签名的数据切实看参数需要的是哪个, 代码注释很清楚,在这里背坑了一次


预支付订单完成,就是回调函数,回调函数切记不能有任何参数,最好单独一个文件


下面即使代码


class Pay { protected function _initialize() { //微信支付参数配置(appid,商户号,支付秘钥) $config = array('appid' => 'xxxxxxxxxxxxxx','mch_id'=> 'xxxxxxxx','pay_api_key' => 'xxxxxxxxxxxxxxxxxxx', ); $this->config = $config; }


/** * 预支付请求接口(POST) * @author * @version * * @param string $openidopenid * @param string $body 商品简单描述 * @param string $order_sn 订单编号 * @param string $total_fee 金额 * @return json的数据 */ public function prepay(){// openid JSAPI不能为空 $openid = 'openid'; $body = '充值'; $order_sn = time() . '_' . $this->getNonceStr(5); // $total_fee = input('money') * 100; // 单位元 $total_fee = 1; // 分


//统一下单参数构造 $param = array('appid'=> $this->config['appid'],'mch_id'=> $this->config['mch_id'],'nonce_str' => $this->getNonceStr(32),'body'=> $body,'out_trade_no' => $order_sn,'total_fee' => $total_fee,'spbill_create_ip' => get_client_ip(),'notify_url'=> 'http://'.$_SERVER['HTTP_HOST'].'/api/notify/callback','trade_type'=> 'JSAPI','openid'=> $openid );


// 统一下订单签名 $param['sign'] = $this->makeSign($param); //同意下订单请求数据 $xml = $this->arrayToXml($param); $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $res = $this->curl_post_ssl($url, $xml); if(!$res){return $this->exit_json("Can't connect the server", 1); }


$content = $this->xmlToArray($res); // 成功 if ($content['return_code'] == 'SUCCESS' && $content['result_code'] == 'SUCCESS') {$content['ctime'] = (string)time();// 小程序签名,签名数据是下订单返回的数据!!!$params = ['appId' => $this->config['appid'],'timeStamp' => $content['ctime'],'nonceStr' => $content['nonce_str'],'package'=> 'prepay_id='.$content['prepay_id'],'signType' => 'MD5',];$params['paySign'] = $this->makeSign($params);$content['paySign'] = $params['paySign'];


// 订单入库# code 数据库操作


return $this->exit_json('订单已生成', 0, $content);


} else if(strval($content['result_code']) == 'FAIL'){return $this->exit_json(strval($content['err_code_des'], 1)); } else if(strval($content['return_code']) == 'FAIL'){return $this->exit_json(strval($content['return_msg']), 1 ); } else {return $this->exit_json('失败', 1); }


}/** * 进行支付接口(POST) * @author * @version 2018-02-03 * * @param string $prepay_id 预支付ID(调用prepay()方法之后的返回数据中获取) * @return json的数据 */ // public function pay(){ // $config = $this->config; // $prepay_id = I('post.prepay_id');// $data = array( // 'appId' => $config['appid'], // 'timeStamp' => time(), // 'nonceStr' => $this->getNonceStr(), // 'package'=> 'prepay_id='.$prepay_id, // 'signType' => 'MD5' // );// $data['paySign'] = $this->makeSign($data);// $this->ajaxReturn($data); // }


//微信支付回调验证public function notify(){ $xml = $GLOBALS['HTTP_RAW_POST_DATA'];// 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了 //file_put_contents(APP_ROOT.'/Statics/log2.txt',$res,FILE_APPEND);//将服务器返回的XML数据转化为数组 $data = $this->xmlToArray($xml); // 保存微信服务器返回的签名sign $data_sign = $data['sign']; // sign不参与签名算法 unset($data['sign']); $sign = $this->makeSign($data);// 判断签名是否正确 判断支付状态 if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) {$result = $data;//获取服务器返回的数据$order_sn = $data['out_trade_no']; //订单单号$openid = $data['openid']; //付款人openID$total_fee = $data['total_fee']; //付款金额$transaction_id = $data['transaction_id'];//微信支付流水号 //更新数据库$this->updateDB($order_sn,$openid,$total_fee,$transaction_id);}else{$result = false; } // 返回状态给微信服务器 if ($result) {$str=''; }else{$str=''; } echo $str; return $result;} // ----------------------用到的函数----------------------


/** * 转化json数据,输出 * @param [type] $msg[description] * @param integer $error [description] * @param [type] $data [description] * @param string $ek[description] * @return [type] [description] */protected function exit_json($msg, $error = 1, $data = null, $ek = 'error'){$jsonArray = array ($ek => $error,'msg' => $msg);if(!empty($data)){$jsonArray['data'] = $data;}exit(json_encode($jsonArray));} /** * 将一个数组转换为 XML 结构的字符串 * @author * @version 2018-02-03 * * @param array $arr 要转换的数组 * @param int $level 节点层级, 1 为 Root. * @return string XML 结构的字符串 */ protected function arrayToXml($arr, $level = 1) { $s = $level == 1 ? "" : ''; foreach($arr as $tagname => $value) {if (is_numeric($tagname)) {$tagname = $value['TagName'];unset($value['TagName']);}if(!is_array($value)) {$s .= "<{$tagname}>".(!is_numeric($value) ? '' : '')."";} else {$s .= "<{$tagname}>" . $this->array2xml($value, $level + 1)."";} } $s = preg_replace("/([/x01-/x08/x0b-/x0c/x0e-/x1f])+/", ' ', $s); return $level == 1 ? $s."" : $s; } /** * 将xml转为array * @author * @version 2018-02-03 * * @param string$xml xml字符串 * @return array转换得到的数组 */ protected function xmlToArray($xml){//禁止引用外部xml实体 libxml_disable_entity_loader(true); $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);return $result; } /** * 产生随机字符串,不长于32位 * @author * @version 2018-02-03 * * @param int $length * @return 产生的随机字符串 */ protected function getNonceStr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789";$str =""; for ( $i = 0; $i < $length; $i++ ) { $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);} return $str; }


/** * 生成签名 * @author * @version 2018-02-03 * * @return 签名 */ protected function makeSign($data){ //获取微信支付秘钥 $key = $this->config['pay_api_key']; // 去空 $data=array_filter($data); //签名步骤一:按字典序排序参数 ksort($data); $string_a=http_build_query($data); $string_a=urldecode($string_a); //签名步骤二:在string后加入KEY //$config=$this->config; $string_sign_temp=$string_a."&key=".$key; //签名步骤三:MD5加密 $sign = md5($string_sign_temp); // 签名步骤四:所有字符转为大写 $result=strtoupper($sign); return $result; } /** * CURL微信支付发起请求(XML格式) * @author * @version 2018-02-03 * * @return */ protected function curl_post_ssl($url, $xmldata, $second=30,$aHeader=array()){ $ch = curl_init(); //超时时间 curl_setopt($ch,CURLOPT_TIMEOUT,$second); curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1); //这里设置代理,如果有的话 //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98'); //curl_setopt($ch,CURLOPT_PROXYPORT, 8080); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); if( count($aHeader) >= 1 ){curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader); } curl_setopt($ch,CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata); $data = curl_exec($ch); if($data){curl_close($ch);return $data; } else {$error = curl_errno($ch);echo "call faild, errorCode:$error/n";curl_close($ch);return false; } } }

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台