微信小程序支付中的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

相关文章

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

Python使用Pandas对比两列数据取最大值的五种方法

《Python使用Pandas对比两列数据取最大值的五种方法》本文主要介绍使用Pandas对比两列数据取最大值的五种方法,包括使用max方法、apply方法结合lambda函数、函数、clip方法、w... 目录引言一、使用max方法二、使用apply方法结合lambda函数三、使用np.maximum函数

Qt 中集成mqtt协议的使用方法

《Qt中集成mqtt协议的使用方法》文章介绍了如何在工程中引入qmqtt库,并通过声明一个单例类来暴露订阅到的主题数据,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一,引入qmqtt 库二,使用一,引入qmqtt 库我是将整个头文件/源文件都添加到了工程中进行编译,这样 跨平台

Nginx设置连接超时并进行测试的方法步骤

《Nginx设置连接超时并进行测试的方法步骤》在高并发场景下,如果客户端与服务器的连接长时间未响应,会占用大量的系统资源,影响其他正常请求的处理效率,为了解决这个问题,可以通过设置Nginx的连接... 目录设置连接超时目的操作步骤测试连接超时测试方法:总结:设置连接超时目的设置客户端与服务器之间的连接

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程