PHP实现 APP端微信支付功能

前面已经写了手机APP支付宝支付,今天再把手机APP微信支付补上,前期的准备工作在这里就不多说了,可以参考,一定要仔细阅读开发文档,可以让你少踩点坑;准备工作完成后就是配置参数,调用统一下单接口,支付后异步回调三部曲啦;

1.我封装好的一个支付类文件,多余的东西都去除掉了,并且把配置参数放到了这个支付类中,只需要修改Weixinpayandroid方法内的几个参数就可以直接复制使用:

"",/*微信开放平台上的应用id*/ 'mch_id' => "",/*微信申请成功之后邮件中的商户id*/ 'api_key' => "",/*在微信商户平台上自己设定的api密钥 32位*/ ); //服务器异步通知页面路径(必填) public $notify_url = ''; //商户订单号(必填,商户网站订单系统中唯一订单号) public $out_trade_no = ''; //商品描述(必填,不填则为商品名称) public $body = ''; //付款金额(必填) public $total_fee = 0; //自定义超时(选填,支持dhmc) public $time_expire = ''; private $WxPayHelper; public function Weixinpayandroid($total_fee,$tade_no) { $this->total_fee = intval($total_fee * 100);//订单的金额 1元 $this->out_trade_no = $tade_no;// date('YmdHis') . substr(time(),- 5) . substr(microtime(),2,5) . sprintf('%02d',rand(0,99));//订单号 $this->body = 'wxpay';//支付描述信息 $this->time_expire = date('YmdHis',time() + 86400);//订单支付的过期时间(eg:一天过期) $this->notify_url = "http://www.ceshi.com/notifyandroid";//异步通知URL(更改支付状态) //数据以JSON的形式返回给APP $app_response = $this->doPay(); if (isset($app_response['return_code']) && $app_response['return_code'] == 'FAIL') { $errorCode = 100; $errorMsg = $app_response['return_msg']; $this->echoResult($errorCode,$errorMsg); } else { $errorCode = 0; $errorMsg = 'success'; $responseData = array( 'notify_url' => $this->notify_url,'app_response' => $app_response,); $this->echoResult($errorCode,$errorMsg,$responseData); } } //接口输出 function echoResult($errorCode = 0,$errorMsg = 'success',$responseData = array()) { $arr = array( 'errorCode' => $errorCode,'errorMsg' => $errorMsg,'responseData' => $responseData,); exit(json_encode($arr)); //exit可以正常发送给APP json数据 // return json_encode($arr); //在TP5中return这个json数据,APP接收到的是null,无法正常吊起微信支付 } function getVerifySign($data,$key) { $String = $this->formatParameters($data,false); //签名步骤二:在string后加入KEY $String = $String . "&key=" . $key; //签名步骤三:MD5加密 $String = md5($String); //签名步骤四:所有字符转为大写 $result = strtoupper($String); return $result; } function formatParameters($paraMap,$urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($k=="sign"){ continue; } if ($urlencode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0) { $reqPar = substr($buff,strlen($buff) - 1); } return $reqPar; } /** * 得到签名 * @param object $obj * @param string $api_key * @return string */ function getSign($obj,$api_key) { foreach ($obj as $k => $v) { $Parameters[strtolower($k)] = $v; } //签名步骤一:按字典序排序参数 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters,false); //签名步骤二:在string后加入KEY $String = $String."&key=".$api_key; //签名步骤三:MD5加密 $result = strtoupper(md5($String)); return $result; } /** * 获取指定长度的随机字符串 * @param int $length * @return Ambigous */ function getRandChar($length){ $str = null; $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; $max = strlen($strPol)-1; for($i=0;$i<$length;$i++){ $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数 } return $str; } /** * 数组转xml * @param array $arr * @return string */ function arrayToXml($arr) { $xml = ""; foreach ($arr as $key=>$val) { if (is_numeric($val)) { $xml.="<".$key.">".$val.""; return $xml; } /** * 以post方式提交xml到对应的接口url * * @param string $xml 需要post的xml数据 * @param string $url url * @param bool $useCert 是否需要证书,默认不需要 * @param int $second url执行超时时间,默认30s * @throws WxPayException */ function postXmlCurl($xml,$url,$second=30,$useCert=false,$sslcert_path='',$sslkey_path='') { $ch = curl_init(); //设置超时 curl_setopt($ch,CURLOPT_TIMEOUT,$second); curl_setopt($ch,CURLOPT_URL,$url); //设置header curl_setopt($ch,CURLOPT_HEADER,FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); if($useCert == true){ curl_setopt($ch,TRUE); curl_setopt($ch,2);//严格校验 //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLCERT,$sslcert_path); curl_setopt($ch,CURLOPT_SSLKEYTYPE,CURLOPT_SSLKEY,$sslkey_path); } //post提交方式 curl_setopt($ch,CURLOPT_POST,CURLOPT_POSTFIELDS,$xml); //运行curl $data = curl_exec($ch); //返回结果 if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); return false; } } /** * 获取当前服务器的IP * @return Ambigous */ function get_client_ip() { if (isset($_SERVER['REMOTE_ADDR'])) { $cip = $_SERVER['REMOTE_ADDR']; } elseif (getenv("REMOTE_ADDR")) { $cip = getenv("REMOTE_ADDR"); } elseif (getenv("HTTP_CLIENT_IP")) { $cip = getenv("HTTP_CLIENT_IP"); } else { $cip = "127.0.0.1"; } return $cip; } /** * 将数组转成uri字符串 * @param array $paraMap * @param bool $urlencode * @return string */ function formatBizQueryParaMap($paraMap,$urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($urlencode) { $v = urlencode($v); } $buff .= strtolower($k) . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0) { $reqPar = substr($buff,strlen($buff)-1); } return $reqPar; } /** * XML转数组 * @param unknown $xml * @return mixed */ function xmlToArray($xml) { //将XML转为array $array_data = json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true); return $array_data; } public function chkParam() { //用户网站订单号 if (empty($this->out_trade_no)) { die('out_trade_no error'); } //商品描述 if (empty($this->body)) { die('body error'); } if (empty($this->time_expire)){ die('time_expire error'); } //检测支付金额 if (empty($this->total_fee) || !is_numeric($this->total_fee)) { die('total_fee error'); } //异步通知URL if (empty($this->notify_url)) { die('notify_url error'); } if (!preg_match("#^http:\/\/#i",$this->notify_url)) { $this->notify_url = "http://" . $_SERVER['HTTP_HOST'] . $this->notify_url; } return true; } /** * 生成支付(返回给APP) * @return boolean|mixed */ public function doPay() { //检测构造参数 $this->chkParam(); return $this->createAppPara(); } /** * APP统一下单 */ private function createAppPara() { $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $data["appid"] = $this->config['appid'];//微信开放平台审核通过的应用APPID $data["body"] = $this->body;//商品或支付单简要描述 $data["mch_id"] = $this->config['mch_id'];//商户号 $data["nonce_str"] = $this->getRandChar(32);//随机字符串 $data["notify_url"] = $this->notify_url;//通知地址 $data["out_trade_no"] = $this->out_trade_no;//商户订单号 $data["spbill_create_ip"] = $this->get_client_ip();//终端IP $data["total_fee"] = $this->total_fee;//总金额 $data["time_expire"] = $this->time_expire;//交易结束时间 $data["trade_type"] = "APP";//交易类型 $data["sign"] = $this->getSign($data,$this->config['api_key']);//签名 $xml = $this->arrayToXml($data); $response = $this->postXmlCurl($xml,$url); //将微信返回的结果xml转成数组 $responseArr = $this->xmlToArray($response); if(isset($responseArr["return_code"]) && $responseArr["return_code"]=='SUCCESS'){ return $this->getOrder($responseArr['prepay_id']); } return $responseArr; } /** * 执行第二次签名,才能返回给客户端使用 * @param int $prepayId:预支付交易会话标识 * @return array */ public function getOrder($prepayId) { $data["appid"] = $this->config['appid']; $data["noncestr"] = $this->getRandChar(32); $data["package"] = "Sign=WXPay"; $data["partnerid"] = $this->config['mch_id']; $data["prepayid"] = $prepayId; $data["timestamp"] = time(); $data["sign"] = $this->getSign($data,$this->config['api_key']); $data["packagestr"] = "Sign=WXPay"; return $data; } /** * 异步通知信息验证 * @return boolean|mixed */ public function verifyNotify() { $xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : ''; if(!$xml){ return false; } $wx_back = $this->xmlToArray($xml); if(empty($wx_back)){ return false; } $checkSign = $this->getVerifySign($wx_back,$this->config['api_key']); if($checkSign=$wx_back['sign']){ return $wx_back; }else{ return false; } } }

2.创建控制器定义统一下单接口和支付后的异步回调接口:

verifyNotify(); if ($verify_result['return_code']=='SUCCESS' && $verify_result['result_code']=='SUCCESS') {   //商户订单号   $out_trade_no = $verify_result['out_trade_no'];   //交易号   $trade_no = $verify_result['transaction_id'];   //交易状态   $trade_status = $verify_result['result_code'];   //支付金额   $total_fee = $verify_result['total_fee']/100;   //支付过期时间   $pay_date = $verify_result['time_end'];   $order = new Order();   $ret = $order->getOrderN2($out_trade_no); //获取订单信息   $total_amount=$ret['money'];   if ($total_amount==$total_fee) {   // 验证成功 修改数据库的订单状态等 $result['out_trade_no']为订单号   //此处写自己的逻辑代码   } exit(''); }else{ exit(''); } }

//调用统一下单接口生成预支付订单并把数据返回给APP
public function wxpayandroid(Request $request)
{
$param = $request->param(); //接收值

$tade_no = $param['orderCode'];
$order = new Order(); //实例化订单
$ret = $order->getOrderN2($tade_no); //查询订单信息
$total_fee = $ret['money']; //订单总金额

$wxpayandroid = new \Wxpayandroid; //实例化微信支付类
$res = $wxpayandroid->Weixinpayandroid($total_fee,$tade_no); //调用weixinpay方法

}

封装一个支付类文件,并把配置参数放到支付类内,再定义控制器创建两个方法,这样两步就可以把手机APP微信支付搞定啦。

总结

以上所述是小编给大家介绍的PHP实现 APP端微信支付功能,希望对大家有所帮助。程序员遇到问题都会上(编程之家jb51.cc)查找问题解答方法!如果觉得站点还不错,随手转发给程序员朋友一下!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读8.4k次,点赞8次,收藏7次。SourceCodester Online Tours & Travels Management System pay.php sql injectionLine 16 of pay.php invokes a SQL query built using unvalidated input. This call could allow an attacker to modify the statement’s meaning or to execute arbitrary SQL commands.SQL
文章浏览阅读3.4k次,点赞46次,收藏51次。本文为大家介绍在windwos系统搭建typecho博客+cpolar内网穿透工具将博客发布到公共网络环境,实现远程也可以访问和操作。_windows搭建typecho
文章浏览阅读1.1k次。- php是最优秀, 最原生的模板语言, 替代语法,让php更加的优雅的与html生活在一起 -->请放心, 最终生成的,或者说用户最终看到的,仍然是一个html文档, php代码中的内容不会被泄漏的。-- 将php与html代码混编的时候,大括号很容易造成配对错误,最好杜绝它 -->php标签内部代码由php.exe解释, php标签之外的代码原样输出,仍由web服务器解析。-- 所以php的流程控制语句, 都提供了替代语法,用冒号代替大括号 -->php echo '百变鹏仔'?_利用php将静态页面修改为动态页面
文章浏览阅读1.1k次,点赞18次,收藏15次。整理K8s网络相关笔记博文内容涉及 Linux network namespace 认知以及彼此通信Demo,实际中的应用理解不足小伙伴帮忙指正不必太纠结于当下,也不必太忧虑未来,当你经历过一些事情的时候,眼前的风景已经和从前不一样了。——村上春树。_linux network namespace 多端通信 模式认知
文章浏览阅读1.2k次,点赞22次,收藏19次。此网络模型提供了一个逻辑二层(L2)网络,该网络封装在跨 Kubernetes 集群节点的现有三层(L3)网络拓扑上。使用此模型,可以为容器提供一个隔离的 L2 网络,而无需分发路由。封装网络带来了少量的处理开销以及由于覆盖封装生成 IP header 造成的 IP 包大小增加。封装信息由 Kubernetes worker 之间的 UDP 端口分发,交换如何访问 MAC 地址的网络控制平面信息。此类网络模型中常用的封装是 VXLAN、Internet 协议安全性 (IPSec) 和 IP-in-IP。_k8s网络组件对比
文章浏览阅读1.1k次,点赞14次,收藏19次。当我们谈论网络安全时,我们正在讨论的是保护我们的在线空间,这是我们所有人的共享责任。网络安全涉及保护我们的信息,防止被未经授权的人访问、披露、破坏或修改。
文章浏览阅读1.3w次,点赞3次,收藏7次。尽管您可以通过 ping 命令解析出网站的 IP 地址,但是可能在浏览器中访问时仍然遇到问题,这可能是因为浏览器使用的 DNS 解析结果不同于 ping 命令使用的解析结果。可能是因为您的网络或设备上设置了防火墙,阻止了对特定网站的访问。有些国家或组织可能会对特定的域名进行屏蔽,从而阻止访问相关网站。如果您的网络使用代理服务器进行访问控制,可能会由于代理服务器的配置问题导致无法访问某些网站。即使您的网络和设备一切正常,目标网站本身可能也存在问题,例如服务器故障、维护或过载,导致无法访问。_能ping通打不开网页
文章浏览阅读839次,点赞22次,收藏19次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。
文章浏览阅读2.1k次,点赞31次,收藏22次。基于微信小程序奶茶点餐外卖系统设计与实现(PHP后台+Mysql)可行性分析毕设源代码毕业设计,数据安全和系统稳定性以及团队能力和资源配备方面都具备较好的条件。因此,该项目的可行性较高。:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;微信小程序作为一种快捷、方便的移动应用形式,成为很多用户点餐外卖的首选。项目的界面和功能都可以定制,包安装运行!项目配有对应开发文档、开题报告、任务书、PPT、论文模版等。
文章浏览阅读1.8k次,点赞52次,收藏38次。本文主要通过对系统的前台系统和后台管理系统进行了功能性需求分析,对系统的安全性和可扩展性进行了非功能性需求分析。在详细的需求分析的基础上,根据系统的功能设计确定了数据库结构,实现完整的代码编写。Lucky+Baby母婴用品网站使用 Dreamweaver、HBuilder代码编辑器、Apache服务器等开发工具,完成了系统的主要模块的页面设计和功能实现。本文展示了首页页面的实现效果图,并通过代码和页面介绍了用户注册功能、商品搜索功能、生成订单和查看我的订单功能、在线付款功能功能的实现过程。
文章浏览阅读1.5k次,点赞45次,收藏40次。本设计主要实现集人性化、高效率、便捷等优点于一身的人事信息管理系统,完成首页、系统用户、通知公告、部门信息、员工薪资、考勤签到、员工请假、招聘信息、应聘信息等功能模块。
文章浏览阅读1k次。该错误通常出现在数据库读取结果集数据时,比如当我们写好SQL语句从数据库读取数据时,本身应该返回结果集,再给结果集中读取数据。解决思路:这种错误一般是因为echo后面输出了一个数组导致的,或者是数组作为字符串进行拼接运算时导致的。该错误直译为:警告:mysqli_fetch_assoc函数期望参数1是mysqli的结果集,但是给了一个布尔值。这种错误是PHP解析器在解析时遇到了语法错误,直译为:解析错误:语法错误,意料之外的...该错误直译为:提示:未定义的索引:username。_array to string conversion in
文章浏览阅读2.7w次。解决http请求报错context deadline exceeded (Client.Timeout exceeded while awaiting headers)_context deadline exceeded (client.timeout exceeded while awaiting headers)
文章浏览阅读1.3k次,点赞26次,收藏24次。复杂网络是一种由大量相互连接的元素(节点或顶点)组成的网络结构,这些连接通常是非常复杂和动态的。这些网络可以在各种领域中发现,包括社交网络、生物学系统、信息技术和交通系统等。_代理建模
文章浏览阅读2.6k次,点赞76次,收藏71次。epoll详解,事件模型,ET/LT模式,并通过三个示例进行代码实现。
文章浏览阅读3.3k次。罗拉ROLA-IP是一家来自纽约的代理IP提供商,由李嘉诚先生投资建设,韩国人工智能、自动驾驶、虚拟现实方面的领军企业World IT Show投资入股,由美国纽约大学IT管理教授团队研究开发,进入中国市场6年多,全世界设有多个分子公司。接下来,我们要检查代理和防火墙的设置,因为在绝大多数情况下,它们是导致这个错误的原因,尤其是当用户使用免费代理时。对网站的访问受阻实际上是一个非常常见的错误,它既可能是由于物理原因(硬件问题)造成的,也可能是由于软件错误引起的。检查代理设置,并确保其正确配置。_无法访问此网站,检查代理服务器和防火墙
文章浏览阅读1.1k次,点赞14次,收藏20次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。_php洗车服务预约管理系统php源码
文章浏览阅读1.1k次。桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
文章浏览阅读936次,点赞22次,收藏17次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。
文章浏览阅读822次,点赞15次,收藏14次。在整个设计过程中,要确定可能的具体解决方案,以实现每一个小的最终目标,对于每一个小目标,我们首先必须了解一些相关的需求分析信息。除了以上作品下面是2023-2024年最新100套计算机专业原创的毕业设计源码+数据库,是近期作品,如果你的题目刚好在下面可以文末领取java源码参考。springboot基于springboot的在线考试系统。springboot基于springboot的商城购物系统。springboot基于微信小程序的智慧校园设计与实现。springboot基于用户的协同过滤算法的话题推荐。