PHP:微信小程序调用【统一下单】【微信支付】【支付回调】API;XML转Array,Array转XML方法(通用)
1、微信公众号、微信小程序开发过程中,第三方服务器与微信服务器数据交互,需要进行数据转换,必须用到这两个函数:
分别是xml_to_array、array_to_xml ;
/** * 输出xml字符(数组转换成xml) * @param $params 参数名称 * return string 返回组装的xml **/ public function array_to_xml( $params ){ if(!is_array($params)|| count($params) <= 0) { return false; } $xml = "<xml>"; foreach ($params as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } /** * 将xml转为array * @param string $xml * return array */ public function xml_to_array($xml){ if(!$xml){ return false; } //将XML转为array //禁止引用外部xml实体 libxml_disable_entity_loader(true); $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $data; }
2、拼接参数,将数组转换成键值对形式的字符串:key=value&k=v
/** * 将参数拼接为url: key=value&key=value * @param $params * @return string */ public function ToUrlParams( $params ){ $string = ''; if( !empty($params) ){ $array = array(); foreach( $params as $key => $value ){ $array[] = $key.'='.$value; } $string = implode("&",$array); } return $string; }
3、微信小程序生成签名,makeSign($params,$KEY),第一个参数是微信官方文档需要的参数;第二个参数是 申请微信支付获得的KEY
/** * 生成签名, $KEY就是支付key * @return 签名 */ public function MakeSign( $params,$KEY){ //签名步骤一:按字典序排序数组参数 ksort($params); $string = $this->ToUrlParams($params); //参数进行拼接key=value&k=v //签名步骤二:在string后加入KEY $string = $string . "&key=".$KEY; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; }
4、微信小程序的签名,总共需要三次;期中前两次是必须的,最后一次尽量加上
4.1 第一次是【统一下单】,将所有需要的信息进行生成签名,包括:
$post['appid'] = $appid;
$post['body'] = $body;
$post['mch_id'] = $mch_id;
$post['nonce_str'] = $nonce_str;//随机字符串
$post['notify_url'] = $notify_url;
$post['openid'] = $openid;
$post['out_trade_no'] = $out_trade_no;
$post['spbill_create_ip'] = $spbill_create_ip;//服务器终端的ip
$post['total_fee'] = intval($total_fee); //总金额 最低为一分钱 必须是整数
$post['trade_type'] = $trade_type;
$sign = $this->MakeSign($post,$KEY); //签名
..等等信息;
4.2 第二次是根据【统一下单】获得的"PREPAY_ID",和申请支付获得的KEY,进行makeSign签名,返回给前端(如JS、APP等)进行调用wx.requestPayment({...})微信支付,包括:
$tmp['appId'] = $appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time";
//上面是签名所需数据,下面是返回数据
$data['timeStamp'] = "$time";
$data['nonceStr'] = $nonce_str;
$data['signType'] = 'MD5';
$data['paySign'] = $this->MakeSign($tmp,$KEY);
$data['package'] = 'prepay_id='.$array['PREPAY_ID'];
($array是【统一下单】返回的数据,经过了xml_to_array处理)
4.3 第三次是微信将支付结果通知给商户,商户需要进行处理通知结果。(通俗点:就是微信告诉你,用户支付成功,你要给微信回一句话:我知道了。)
这个时候也需要makeSing签名,具体代码如下:
/* 微信支付完成,回调地址url方法 xiao_notify_url() */ public function xiao_notify_url(){ $KEY = '你申请微信支付的KEY'; $post = post_data(); //接受POST数据 $post_data = $this->xml_to_array($post); //微信支付成功,返回回调地址url的数据:XML转数组Array $postSign = $post_data['sign']; unset($post_data['sign']); //这里很重要哦,一定要将返回的sign剔除掉 /* 微信官方提醒: * 商户系统对于支付结果通知的内容一定要做【签名验证】, * 并校验返回的【订单金额是否与商户侧的订单金额】一致, * 防止数据泄漏导致出现“假通知”,造成资金损失。 */ ksort($post_data);// 对数据进行排序 //正常情况微信是不会返回支付的key的,为保万一我们判断一下 --xzz 0622 if($post_data['key']){ $str = $this->ToUrlParams($post_data);//对数组数据拼接成key=value字符串 }else{ $str = $this->ToUrlParams($post_data).'&key='.$KEY; //这里也一定要加上key,不然签名就错了 } $user_sign = strtoupper(md5($str)); //再次生成签名,与$postSign比较 $where['crsNo'] = $post_data['out_trade_no']; $order_msg = M('home_order','xxf_witkey_')->where($where)->find(); /* * 分别判断返回状态码、返回签名sign、返回订单总金额,三者同时为真,订单交易成功,状态修改为‘ok’ */ if($post_data['return_code']=='SUCCESS'&&$postSign==$user_sign&&$order_msg['order_amount']*100==$post_data['total_fee']){ /* * 首先判断,订单是否已经更新为ok,因为微信会总共发送8次回调确认 * 其次,订单已经为ok的,直接返回SUCCESS * 最后,订单没有为ok的,更新状态为ok,返回SUCCESS */ if($order_msg['order_status']=='ok'){ $this->return_success(); }else{ $updata['order_status'] = 'ok'; if(M('home_order','xxf_witkey_')->where($where)->save($updata)){ $this->return_success(); } } }else{ echo '微信支付失败'; } } /* * 给微信发送确认订单金额和签名正确,SUCCESS信息 -xzz0521 */ private function return_success(){ $return['return_code'] = 'SUCCESS'; $return['return_msg'] = 'OK'; $xml_post = '<xml> <return_code>'.$return['return_code'].'</return_code> <return_msg>'.$return['return_msg'].'</return_msg> </xml>'; echo $xml_post;exit; }
5、再次提醒一下,这个代码是给微信小程序用的,其他的别照搬哦。