微信小程序支付中的prepay_id获取方法,以及微信支付统一签名算法闭坑

2024-05-16 09:58

本文主要是介绍微信小程序支付中的prepay_id获取方法,以及微信支付统一签名算法闭坑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

class Wechat
{//公众号的或者小程序支付参数private $appId = "*************";private $appSecret = "*************";//商家的配置信息private $mch_id = "*************";private $mch_key = "*************";//回调地址public $notify_url = '';//退款回掉地址public $refund_notify_url = '';private $request;private $nonce_str;public function __construct(){$this->request = Request::instance();$this->notify_url = base_url() . 'notice.php';$this->refund_notify_url = base_url() . 'refund.php';$this->nonce_str = md5(date('YmdHis') . time() . rand(1000, 9999));}//小程序登录/*** @param $code  获取微信支付的登录code* @return mixed*/public function wxLogin($code){$url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $this->appId . "&secret=" . $this->appSecret . "&js_code=" . $code . "&grant_type=authorization_code";return json_decode($this->execute($url), true);}/*** @param $out_trade_no  微信支付唯一订单* @param $openid 微信支付用户的openid* @param $price  订单支付的价格,(单位,元)* @param string $desc 订单描述* @return array|mixed 组装支付参数*/public function getPayParameter($out_trade_no, $openid, $price, $desc = ''){header("Content-type:text/html;charset=utf-8"); //此处进行字符集初始化,$data = array('appid' => $this->appId,'body' => $desc,'mch_id' => $this->mch_id,'nonce_str' => $this->nonce_str,               //随机字符串'notify_url' => $this->notify_url,             //异步回调地址'openid' => $openid,                           //用户登录时获取的code中含有的值'out_trade_no' => $out_trade_no,               //商家订单号'spbill_create_ip' => $this->get_real_ip(),    //APP和网页支付提交用户端ip'total_fee' => $price * 100,                   //订单总额//'total_fee' => 1,'attach' => 'order',           //确定是哪个商家进行的支付'trade_type' => 'JSAPI'           //交易类型);//将数组转化为Xml$data['sign'] = $this->makeSign($data);$abc_xml = $this->arrayToXml($data);//统一下单接口prepay_id$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';$xml = $this->execute($url, $abc_xml, 1);//将XMl转化为数组$info = $this->xml2array($xml);if (!isset($info['prepay_id'])) {return $info;}$params = array('appId' => $this->appId,'nonceStr' => $data['nonce_str'],'package' => 'prepay_id=' . $info['prepay_id'],'signType' => 'MD5','timeStamp' => '' . time(),);$_info['paySign'] = $this->makeSign($params);$_info['timeStamp'] = "" . $params['timeStamp'];$_info['nonceStr'] = $params['nonceStr'];$_info['package'] = $params['package'];$_info['signType'] = $params['signType'];$_info['notify_url'] = $this->notify_url;//请求成功后进行返回数据信息if ($info['return_code'] == 'SUCCESS' || $info['result_code'] == 'SUCCESS') {return $_info;} else {return [];}}/*** @param $openid  支付的用户的openid* @return mixed*/public function userInfo($openid){$token = $this->getWxAccessToken();$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" . $token . "&openid=$openid&lang=zh_CN";return json_decode($this->execute($url), true);}//获取微信的tokenpublic function getWxAccessToken(){$key = $this->appId . 'miniProgram_access_token';$accessToken = Cache::get($key);if ($accessToken) return $accessToken;$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->appId . "&secret=" . $this->appSecret;$con = json_decode($this->execute($url));Cache::set($key, $con->access_token, $con->expires_in);return $con->access_token;}/*** @param $url  请求url地址* @param string $data 请求参数* @param int $post 是否为post* @param int $cert 是否为微信的cert* @return mixed*/private function execute($url, $data = '', $post = 0, $cert = 0){if (is_array($data)) {$data = json_encode($data);}$ch = curl_init();curl_setopt($ch, CURLOPT_HEADER, 0);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);curl_setopt($ch, CURLOPT_POST, $post);if ($post)curl_setopt($ch, CURLOPT_POSTFIELDS, $data);if ($cert) {curl_setopt($ch, CURLOPT_SSLCERT, WEB_PATH . 'cert' . DS . 'apiclient_cert.pem');curl_setopt($ch, CURLOPT_SSLKEY, WEB_PATH . 'cert' . DS . 'apiclient_key.pem');}// curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type:application/json']);curl_setopt($ch, CURLOPT_URL, $url);$result = curl_exec($ch);curl_close($ch);return $result;}function http_post_data($url, $data_string, $header = [], $is_array = 0, $is_key_pem = false){if (is_array($data_string)) {$data_string = json_encode($data_string);}if (!$header) {$header = ["Content-Type: application/json; charset=utf-8","Content-Length: " . strlen($data_string)];} else {$header = array_merge($header, ["Content-Type: application/json; charset=utf-8","Content-Length: " . strlen($data_string)]);}$ch = curl_init();curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);curl_setopt($ch, CURLOPT_HTTPHEADER, $header);curl_setopt($ch, CURLOPT_TIMEOUT, 3);if ($is_key_pem) {$isdir = '/cert/';curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 终止从服务端进行验证curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');//证书类型curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');//CURLOPT_SSLKEY中规定的私钥的加密类型curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem');//证书位置// curl_setopt($ch, CURLOPT_CAINFO, 'PEM');// curl_setopt($ch, CURLOPT_CAINFO, $isdir . 'rootca.pem');}ob_start();curl_exec($ch);$return_content = ob_get_contents();ob_end_clean();$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);if ($is_array) {if (!is_array($return_content)) {$return_content = json_decode($return_content, true);}}return $return_content;}// 数组转化为 xlmpublic function arrayToXml($data){$data['sign'] = $this->makeSign($data);ksort($data);//进行拼接数据$abc_xml = "<xml>";foreach ($data as $key => $val) {if (is_numeric($val)) {$abc_xml .= "<" . $key . ">" . $val . "</" . $key . ">";} else {$abc_xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";}}$abc_xml .= "</xml>";return $abc_xml;}//xlm 转化为数组public function xml2array($xml){if (empty($xml)) {return array();}//禁止引用外部xml实体libxml_disable_entity_loader(true);$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);$val = json_decode(json_encode($xmlstring), true);return $val;}//微信进行拼接signpublic function makeSign($params){//签名步骤一:按字典序排序数组参数ksort($params);$buff1 = '';foreach ($params as $k => $v) {if ($k != "sign" && $v != "" && !is_array($v)) {$buff1 .= $k . "=" . $v . "&";}}$buff1 = trim($buff1, "&");//签名步骤二:在string后加入KEY$string = $buff1 . "&key=" . $this->mch_key;//签名步骤三:MD5加密$string = md5($string);//签名步骤四:所有字符转为大写$result = strtoupper($string);return $result;}//验证图片或者视频是否涉黄public function imgSecCheck($media_url, $media_type = 2){$url = 'https://api.weixin.qq.com/wxa/media_check_async?access_token=' . $this->getWxAccessToken();$return = $this->execute($url, ['media_url' => $media_url,'media_type' => $media_type,], 1);$return = json_decode($return, true);if ($return && $return['errcode'] == 0) {return true;}return false;}//验证发布内容是否违法以及敏感词汇public function msgSecCheck($content = ''){$url = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token=' . $this->getWxAccessToken();$return = $this->execute($url, ['content' => $content], 1);$return = json_decode($return, true);if ($return && $return['errcode'] == 0) {return true;}return false;}/*** [sendMoney 企业付款到零钱]* @param  [type] $amount     [发送的金额(分)目前发送金额不能少于1元]* @param  [type] $re_openid  [发送人的 openid]* @param  string $desc [企业付款描述信息 (必填)]* @param  string $check_name [收款用户姓名 (选填)]* @return [type]             [description]* https://www.cnblogs.com/echoppy/p/8603286.html*/public function sendMoney($amount, $re_openid){$total_amount = (100) * $amount;$data = array('mch_appid' => $this->appId,//商户账号appid'mchid' => $this->mch_id,//商户号'nonce_str' => $this->nonce_str,//随机字符串'partner_trade_no' => date('YmdHis') . rand(1000, 9999),//商户订单号'openid' => $re_openid,//用户openid'check_name' => 'NO_CHECK',//校验用户姓名选项,'amount' => $total_amount,//付款金额,单位为分'desc' => '商户提现',//企业付款描述信息'spbill_create_ip' => $this->get_real_ip(),//Ip地址);//生成签名算法$secrect_key = $this->mch_key;   ///这个就是个API密码。MD5 32位。$data = array_filter($data);ksort($data);$str = '';foreach ($data as $k => $v) {$str .= $k . '=' . $v . '&';}$str .= 'key=' . $secrect_key;$data['sign'] = md5($str);//生成签名算法$xml = $this->arraytoxml($data);$url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; //调用接口//$res = $this->http_post_data($url, $xml)$res = $this->execute($url, $xml, 1, 1);$return = $this->xml2array($res);return $return;}/*** @param $amount  退款金额* @param $re_openid  退款用户的openid* @return bool  退款成功失败* 开发文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4*/public function refundUserMoney($transaction_id, $total_fee, $refund_fee, $out_refund_no){$data = array('appid' => $this->appId,//商户账号appid'mch_id' => $this->mch_id,//商户号'nonce_str' => $this->nonce_str,//随机字符串'transaction_id' => $transaction_id,//微信支付商户号'total_fee' => $total_fee * 100,//订单金额'refund_fee' => $refund_fee * 100,//退款金额'notify_url' => $this->refund_notify_url,//退款金额'out_refund_no' => $out_refund_no,//退款金额);//生成签名算法$secrect_key = $this->mch_key;   ///这个就是个API密码。MD5 32位。$data = array_filter($data);ksort($data);$str = '';foreach ($data as $k => $v) {$str .= $k . '=' . $v . '&';}$str .= 'key=' . $secrect_key;$data['sign'] = md5($str);//生成签名算法$xml = $this->arraytoxml($data);$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";$res = $this->execute($url, $xml, 1, 1);if (!$res) {return false;}//$res = $this->http_post_data($url, $xml);$return = $this->xml2array($res);if ($return['return_code'] == 'SUCCESS') {return true;}return false;}public function get_real_ip(){$ip = $_SERVER['REMOTE_ADDR'];if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {foreach ($matches[0] AS $xip) {if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {$ip = $xip;break;}}} elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {$ip = $_SERVER['HTTP_CLIENT_IP'];} elseif (isset($_SERVER['HTTP_CF_CONNECTING_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CF_CONNECTING_IP'])) {$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];} elseif (isset($_SERVER['HTTP_X_REAL_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_REAL_IP'])) {$ip = $_SERVER['HTTP_X_REAL_IP'];}return $ip ? $ip : '127.0.0.1';}}

 

这篇关于微信小程序支付中的prepay_id获取方法,以及微信支付统一签名算法闭坑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/994585

相关文章

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

SpringBoot日志配置SLF4J和Logback的方法实现

《SpringBoot日志配置SLF4J和Logback的方法实现》日志记录是不可或缺的一部分,本文主要介绍了SpringBoot日志配置SLF4J和Logback的方法实现,文中通过示例代码介绍的非... 目录一、前言二、案例一:初识日志三、案例二:使用Lombok输出日志四、案例三:配置Logback一

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T