Android_APP微信支付之实现代码

来源:互联网 发布:石材仿形机编程说明书 编辑:程序博客网 时间:2024/06/06 14:00

在之前的一篇Android_APP微信支付接口开发中说了大概的实现方式和一些注意细节,这是说在微信支付中应该由我们的服务器来生成支付订单,以及对prepay_id的再次签名都应该在我们的服务器中完成。

下面就贴出服务器端的代码,主要是生成支付订单以及对prepay_id进行签名,然后将生成的签名prepay_id传给客户端,在客户端进行二次签名并调起支付:

<?php$json = stripslashes($_SGET['json']); //去斜杠,stripslashes()函数:删除反斜杠$getarray = json_decode($json,true); //转码,json_decode()函数:对JSON格式的字符串进行编码//json_encode()函数:对变量进行JSON编码//防止SQL注入foreach($getarray as $k=>$v){$str=show_sql_keyword($v);if($str){$msg = urlencode ("含有非法字符");//urlencode()函数:编码URL字符串;urldecode()函数:解码已经编码的URL字符串$data = array(result => 2,msg => $msg);echo urldecode ( json_encode ( $data ) );exit;}}if($getarray['submit']){$OS = $getarray['OS'];$paymentid = $getarray['paymentid'];$username = $getarray['username'];$money = $getarray['money'];$orderNO = $getarray['orderNO'];//判断金额是否为负数    if($money<0){   $msg = urlencode ("提款金额不能为负数");   $data = array(result => 5,msg => $msg);   echo urldecode ( json_encode ( $data ) );   exit;      }$sql = "select `username`,`uid` from ".$_SC['tablepre']."user where `username`='{$username}'";$query = $_SGLOBAL['db']->query($sql);$consignee = $_SGLOBAL['db']->fetch_array($query);//用户判断if($consignee['username'] == ''){$msg = urlencode ("nouser");$data = array(result => 2,msg => $msg);echo urldecode ( json_encode ( $data ) );exit;}//充值金额判断$money = $money;$money_rules = '/^([123456789]+)\d*(\.?\d{0,2})$|^(0{1})(\.{1}\d{0,2})$/';if(!preg_match($money_rules,$money)){ //preg_match()函数:执行一个正则表达式匹配$msg = urlencode ("error");$data = array(result => 4,msg => $msg);echo urldecode ( json_encode ( $data ) );exit;}//订单号判断if($orderNO != ''){$orderNO = $getarray['orderNO']; //如果订单号不为空 则取出数组里的订单号}else{$orderNO = substr(date("YmdHis"),2,8).mt_rand(100000,999999); //否则随机生成一个订单号//记录充值$payorder_data = array('payuserid'=>$consignee['uid'],'orderNO'=>$orderNO,'tradeNO'=>'','payname'=>'','consignee'=>$consignee['username'],'consigneeuid'=>'','money'=>$money,'paymentid'=>$paymentid,'paymentlabel'=>"微信支付",'payresult'=>0,'deliverrs'=>'','paydate'=>'','dateline'=>time(),);    inserttable($_SC['tablepre'],"payorder", $payorder_data, 1 );}//上面大部分代码是根据每个项目需要进行的逻辑处理,下面微信支付生成支付订单以及prepay_id的主要代码$prepayxml='';$data=array();//判断是否是Android端传过来的调起支付if($OS=="Android"){$noncestr=md5(rand());//int rand(void)函数:产生一个随机整数,返回0到getrandMax()之间的伪随机整数。//亦可带参数int rand ( int $min , int $max )$prepayid_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";$appkey='API密钥'; //API密钥,在商户平台设置//注:appid、body、mch_id、notify_url填写上对应的值$preamdata = array ('appid' => 'appid','body' => '标题','input_charset'=>'UTF-8','mch_id'=>'商户号','notify_url'=>'http://www.XXXX.com/payapi/wxnotify.php','out_trade_no'=>$orderNO,'spbill_create_ip'=>"192.168.1.16",'total_fee'=>$money*100,'trade_type'=>"APP","nonce_str"=>$noncestr,);$sign=MakeSign($preamdata,$appkey); //生成sign签名//echo $str;// 参数数组,拼接成XML$preamstr='<?xml version="1.0" encoding="UTF-8"?>';$preamstr.='<xml>';$preamstr.='<appid>appid</appid>'; //appid$preamstr.='<body>标题</body>'; //标题$preamstr.='<input_charset>UTF-8</input_charset>'; //编码,不然body不能出现中文$preamstr.='<mch_id>商户号</mch_id>'; //商户号$preamstr.='<notify_url>http://www.XXXX.com/payapi/wxnotify.php</notify_url>'; //成功支付回调地址$preamstr.='<out_trade_no>'.$orderNO.'</out_trade_no>'; //订单号$preamstr.='<spbill_create_ip>192.168.1.16</spbill_create_ip>'; //ip$preamstr.='<total_fee>'.($money*100).'</total_fee>'; //金额,微信支付默认分为单位,所以要乘以100$preamstr.='<trade_type>APP</trade_type>'; //交易类型$preamstr.='<nonce_str>'.$noncestr.'</nonce_str>';$preamstr.='<sign>'.$sign.'</sign>'; //sign签名$preamstr.='</xml>';//echo $preamstr;//创建一个新curl资源$ch = curl_init ();// print_r($ch);//设置URL和相应的选项curl_setopt ( $ch, CURLOPT_URL, $prepayid_url );curl_setopt ( $ch, CURLOPT_POST, 1 );curl_setopt ( $ch, CURLOPT_HEADER, 0 );curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );curl_setopt ( $ch, CURLOPT_POSTFIELDS, $preamstr );//抓取URL并把它传递给浏览器$return = curl_exec ( $ch );//关闭curl资源,并且释放系统资源curl_close ( $ch );$prepayxml = $return;}elseif($OS=="IOS"){ //判断是否是IOS端传过来的调起支付$noncestr=md5(rand());$prepayid_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";$appkey='API密钥';$preamdata = array ('appid' => 'appid','body' => '标题','input_charset'=>'UTF-8','mch_id'=>'商户号','notify_url'=>'http://www.XXXX.com/payapi/wxnotify.php','out_trade_no'=>$orderNO,'spbill_create_ip'=>"192.168.1.16",'total_fee'=>$money*100,'trade_type'=>"APP","nonce_str"=>$noncestr,);$sign=MakeSign($preamdata,$appkey); //生成sign签名//echo $str;// 参数数组,拼接成XML$preamstr='<?xml version="1.0" encoding="UTF-8"?>';$preamstr.='<xml>';$preamstr.='<appid>appid</appid>';$preamstr.='<body>标题</body>';$preamstr.='<input_charset>UTF-8</input_charset>';$preamstr.='<mch_id>商户号</mch_id>';$preamstr.='<notify_url>http://www.XXXX.com/payapi/wxnotify.php</notify_url>';$preamstr.='<out_trade_no>'.$orderNO.'</out_trade_no>';$preamstr.='<spbill_create_ip>192.168.1.16</spbill_create_ip>';$preamstr.='<total_fee>'.($money*100).'</total_fee>';$preamstr.='<trade_type>APP</trade_type>';$preamstr.='<nonce_str>'.$noncestr.'</nonce_str>';$preamstr.='<sign>'.$sign.'</sign>';$preamstr.='</xml>';//echo $preamstr;//创建一个新curl资源$ch = curl_init ();// print_r($ch);//设置URL和相应的选项curl_setopt ( $ch, CURLOPT_URL, $prepayid_url );curl_setopt ( $ch, CURLOPT_POST, 1 );curl_setopt ( $ch, CURLOPT_HEADER, 0 );curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );curl_setopt ( $ch, CURLOPT_POSTFIELDS, $preamstr );//抓取URL并把它传递给浏览器$return = curl_exec ( $ch );//关闭curl资源,并且释放系统资源curl_close ( $ch );//print_r($return);//echo $return;$prepayxml = $return;}else{$msg = urlencode ("error");$data = array(result => 5,msg => $msg);echo urldecode ( json_encode ( $data ) );exit;}$data['msg']='done';$data['orderno'] = $orderNO;$data['result'] = 1;$str=urldecode ( json_encode ( $data ) );echo substr($str,0,-1).',"prepayxml":"'.$prepayxml.'"}';}/** * 生成签名 * @param $arr 用到的参数数组 * @param $appkey * @return string */function MakeSign($arr,$appkey){//签名步骤一:按字典序排序参数,ksort()函数:对关联数组按照键名进行升序排序ksort($arr);$string = ToUrlParams($arr);//签名步骤二:在string后加入KEY$string = $string . "&key=".$appkey;//签名步骤三:MD5加密$string = md5($string);//签名步骤四:所有字符转为大写$result = strtoupper($string);return $result;}/** * 将参数进行拼接 * @param $arr 要拼接的数组 * @return string 拼接后得到的字符串 */function ToUrlParams($arr){$buff = "";foreach ($arr as $k => $v){if($k != "sign" && $v != "" && !is_array($v)){$buff .= $k . "=" . $v . "&";}}//trim()函数:移除字符串两侧的空白字符或其他预定义字符$buff = trim($buff, "&");return $buff;}?>

下面是调起支付后回调页面的服务器处理代码:

<?php$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];//writelog($postStr);//$pos = strpos($postStr, 'xml');//simplexml_load_string()函数:把XML字符串载入对象中,如果失败,则返回false$obj=simplexml_load_string($postStr,'SimpleXMLElement', LIBXML_NOCDATA);$obj=json_decode(json_encode($obj), true);$sign=$obj['sign'];$orderno=$obj['out_trade_no']; $tradeno=$obj['transaction_id'];$return_code = $obj['return_code'];$return_msg = $obj['return_msg'];if($return_code == 'SUCCESS'){$xmlstr="<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg><sign><![CDATA[".$sign."]]></sign></xml>";//下面是我们根据项目需要而进行的处理echo $xmlstr;include_once('../common.php');$data = array( "tradeNO"=>$tradeno,"payresult"=> 1,"paydate"=> $_SGLOBAL['timestamp'],);updatetable($_SC['tablepre'],"payorder",$data,"orderNO='".$orderno."'",0);$sql = "select * from ".$_SC['tablepre']."payorder where orderNO='$orderno'";$query = $_SGLOBAL['db']->query($sql);$payorder = $_SGLOBAL['db']->fetch_array($query);$money=$payorder['money'];$sql="update ".$_SC['tablepre']."user set money=money+$money where username='".$payorder['consignee']."'";$query = $_SGLOBAL['db']->query($sql);//记录充值记录$data=array("uid"=> $payorder['payuserid'],"wishid"=> 0,"iotype"=> 1,"buytype"=> 9,"money"=> $money,"description"=> "微信充值".$money."元","dateline"=> $_SGLOBAL['timestamp'],);    inserttable($_SC['tablepre'],"userfinance", $data, 1 );}else{$xmlstr="<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[".$return_msg."]]></return_msg></xml>";echo $xmlstr;}//日志记录function logger($log_content){    $max_size = 100000;    $log_filename = "log.xml";    if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}    file_put_contents($log_filename,$log_content."\r\n", FILE_APPEND);}exit;?>

最后,贴出客户端接收服务端生成的签名prepay_id再进行二次签名并调起支付的主要代码:

Map<String,String> resultunifiedorder;resultunifiedorder = decodeXml(prepayId);//生成签名参数并发起支付请求genPayReq();public Map<String,String> decodeXml(String content) {try {Map<String, String> xml = new HashMap<String, String>();XmlPullParser parser = Xml.newPullParser();parser.setInput(new StringReader(content));int event = parser.getEventType();while (event != XmlPullParser.END_DOCUMENT) {String nodeName=parser.getName();switch (event) {case XmlPullParser.START_DOCUMENT:break;case XmlPullParser.START_TAG:if("xml".equals(nodeName)==false){xml.put(nodeName,parser.nextText());}break;case XmlPullParser.END_TAG:break;}event = parser.next();}return xml;} catch (Exception e) {Log.e("orion",e.toString());}return null;}   //获取二次签名sign并调起微信支付private void genPayReq() {req.appId = Constants.APP_ID;req.partnerId = Constants.MCH_ID;req.prepayId = resultunifiedorder.get("prepay_id");req.packageValue = "Sign=WXPay";req.nonceStr = genNonceStr();req.timeStamp = String.valueOf(genTimeStamp());List<NameValuePair> signParams = new LinkedList<NameValuePair>();signParams.add(new BasicNameValuePair("appid", req.appId));signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));signParams.add(new BasicNameValuePair("package", req.packageValue));signParams.add(new BasicNameValuePair("partnerid", req.partnerId));signParams.add(new BasicNameValuePair("prepayid", req.prepayId));signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));req.sign = genAppSign(signParams);sb.append("sign\n"+req.sign+"\n\n");Log.e("orion++++++++++  ", signParams.toString());//发送请求调起微信支付msgApi.registerApp(Constants.APP_ID);msgApi.sendReq(req);}

在接收到prepay_id后,须对prepay_id进行解码,最后再调用genPayReq()获取二次签名sign并调起微信支付。

0 0
原创粉丝点击