//微信支付 public function pay(){ $fee = 1;//举例支付0.01,单位是分 $appid = "你的小程序appid";//appid.如果是公众号 就是公众号的appid $body = "你的商品名称"; $mch_id = '你的商户号';//商户号 $nonce_str = $this->nonce_str();//随机字符串 $notify_url = '你的支付成功回调url'; //回调的url【自己填写】,注:此处url必须是外网可访问地址才可以,如果是自己内网服务器不行。 $openid = "支付用户的openid"; //支付用户的openid $out_trade_no = "此处是你生成的订单号";//商户订单号:需要保证随机生成不重复,建议生成20位 $spbill_create_ip = '127.0.0.1';//服务器的ip【自己填写】; $total_fee = $fee*100;// 微信支付单位是分,所以这里需要*100 $trade_type = 'JSAPI';//交易类型 默认 //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错 $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'] = $total_fee;//总金额 $post['trade_type'] = $trade_type; $sign = $this->sign($post);//签名 $post_xml = '<xml> <appid>'.$appid.'</appid> <body>'.$body.'</body> <mch_id>'.$mch_id.'</mch_id> <nonce_str>'.$nonce_str.'</nonce_str> <notify_url>'.$notify_url.'</notify_url> <openid>'.$openid.'</openid> <out_trade_no>'.$out_trade_no.'</out_trade_no> <spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip> <total_fee>'.$total_fee.'</total_fee> <trade_type>'.$trade_type.'</trade_type> <sign>'.$sign.'</sign> </xml> '; // print_r($post_xml);die; //统一接口prepay_id $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $xml = $this->http_request($url,$post_xml); $array = $this->xmlToArray($xml); // print_r($xml);die; if($array['return_code'] == 'SUCCESS' && $array['result_code'] == 'SUCCESS'){ $time = time(); $tempArr=array( 'appId' => $appid, 'nonceStr' => $nonce_str, 'package' => 'prepay_id='.$array['prepay_id'], 'signType' => 'MD5', 'timeStamp' => "$time" ); $data['state'] = 200; $data['timeStamp'] = "$time";//时间戳 $data['nonceStr'] = $nonce_str;//随机字符串 $data['signType'] = 'MD5';//签名算法,暂支持 MD5 $data['package'] = 'prepay_id='.$array['prepay_id'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=* $data['paySign'] = $this->sign($tempArr);//签名,具体签名方案参见微信公众号支付帮助文档; $data['out_trade_no'] = $out_trade_no; $data['orderNumber'] = $orderNumber; $data['sumPrice'] = $sumPrice; }else{ $data['state'] = 0; $data['text'] = "错误"; $data['returnArr'] = $array; } //将此处的$data返回给小程序即可,小程序端发起支付需要用到:timeStamp、nonceStr、package、signType、paySign等参数,我们此处并没有发起真正的支付,仅是向微信发起了统一下单拿到微信返回的相关参数返回给小程序,然后由小程序发起支付 return $data; } //随机32位字符串 private function nonce_str(){ $result = ''; $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz'; for ($i=0;$i<32;$i++){ $result .= $str[rand(0,48)]; } return $result; } //签名 $data要先排好顺序 private function sign($data){ $stringA = ''; foreach ($data as $key=>$value){ if(!$value) continue; if($stringA) $stringA .= '&'.$key."=".$value; else $stringA = $key."=".$value; } $wx_key = '商户key';//申请支付后有给予一个商户账号和密码,登陆后自己设置的key $stringSignTemp = $stringA.'&key='.$wx_key; return strtoupper(md5($stringSignTemp)); } //curl请求 public function http_request($url,$data = null,$headers=array()){ $curl = curl_init(); if( count($headers) >= 1 ){ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); return $output; } //xml转换成数组 private function xmlToArray($xml) { //禁止引用外部xml实体 libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring), true); return $val; }
//小程序支付成功回调函数 public function notify(){ //获取接口数据,如果$_REQUEST拿不到数据,则使用file_get_contents函数获取 $post = $_REQUEST; if ($post == null) { $post = file_get_contents("php://input"); } if ($post == null) { $post = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : ''; } if (empty($post) || $post == null || $post == '') { //阻止微信接口反复回调接口 文档地址 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7,下面这句非常重要!!! $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; echo $str; exit('Notify 非法回调'); } /*****************微信回调返回数据样例******************* $post = '<xml><appid><![CDATA[wx42e35e9cba15a5fc]]></appid> <bank_type><![CDATA[CFT]]></bank_type> <cash_fee><![CDATA[1]]></cash_fee> <fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[N]]></is_subscribe> <mch_id><![CDATA[1509441511]]></mch_id> <nonce_str><![CDATA[UtpvtBhXIqpROhTXNpJSafbcFuPXTprt]]></nonce_str> <openid><![CDATA[oYlJJ5Fs8VzKYE3xOKvKn-IuuMLM]]></openid> <out_trade_no><![CDATA[20190516155797735964]]></out_trade_no> <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code> <sign><![CDATA[8DBFF1A0922A35B081CD09E59FB21EDF]]></sign> <time_end><![CDATA[20190516112925]]></time_end> <total_fee>1</total_fee> <trade_type><![CDATA[JSAPI]]></trade_type> <transaction_id><![CDATA[4200000296201905161862992531]]></transaction_id> </xml>'; *************************微信回调返回*****************/ libxml_disable_entity_loader(true); //禁止引用外部xml实体 $xml = simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);//XML转数组 $post_data = (array)$xml; //将用户支付信息记录日志文件 \Think\Log::record("用户openid:".$post_data['openid']); \Think\Log::record("appId:".$post_data['appid']); \Think\Log::record("订单编号:".$post_data['out_trade_no']); \Think\Log::record("支付金额:".$post_data['total_fee']/100); //此时你就可以进行修改订单状态以及其他的操作了... $out_trade_no=$post_data['out_trade_no']; //订单编号 //阻止微信接口反复回调接口 文档地址 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7,下面这句非常重要!!! $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; echo $str; }
// pages/pay/pay.js Page({ data: { orderId: '', // 订单ID }, onLoad: function (options) { // 从页面参数中获取订单ID this.setData({ orderId: options.orderId }); }, initiatePayment: function () { const that = this; wx.request({ url: 'https://your-backend.com/api/getPayParams', // 后端接口地址 method: 'POST', data: { orderId: that.data.orderId, }, success: function (res) { const payParams = res.data; that.wxPay(payParams); }, fail: function (error) { console.error('Failed to get payment parameters:', error); } }); }, wxPay: function (payParams) { wx.requestPayment({ timeStamp: payParams.timeStamp, nonceStr: payParams.nonceStr, package: payParams.package, signType: payParams.signType, paySign: payParams.paySign, success: function (res) { console.log('Payment success:', res); // 处理支付成功的逻辑 }, fail: function (error) { console.error('Payment failed:', error); // 处理支付失败的逻辑 } }); } });
<!-- pages/pay/pay.wxml --> <view class="container"> <button bindtap="initiatePayment">支付</button> </view>
<?php // config/wechat.php return [ 'appid' => 'your_appid', // 公众号ID 'appsecret' => 'your_appsecret', // 公众号秘钥 'mch_id' => 'your_mch_id', // 商户ID 'key' => 'your_pay_key', // 支付密钥 'notify_url' => 'https://your-backend.com/api/payNotify', // 支付结果通知地址 ];
composer require overtrue/easywechat:~4.0
<?php // application/controller/WechatPayController.php namespace app\controller; use think\Controller; use EasyWeChat\Factory; use think\facade\Config; class WechatPayController extends Controller { public function pay() { $config = Config::get('wechat'); $app = Factory::payment($config); $params = [ 'body' => '订单描述', // 商品描述 'out_trade_no' => '订单号', // 自定义的订单号 'total_fee' => '订单金额(单位:分)', 'notify_url' => $config['notify_url'], 'trade_type' => 'JSAPI', 'openid' => '用户的openid', // 用户的openid ]; $result = $app->order->unify($params); if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') { $prepay_id = $result['prepay_id']; $data = [ 'timeStamp' => strval(time()), 'nonceStr' => $app->utils->createNonceStr(), 'package' => "prepay_id={$prepay_id}", 'signType' => 'MD5', 'paySign' => $app->utils->getPaySign([ 'timeStamp' => $data['timeStamp'], 'nonceStr' => $data['nonceStr'], 'package' => $data['package'], 'signType' => $data['signType'], ], $config['key']), ]; return json($data); } else { return json(['error' => '支付参数生成失败']); } } public function notify() { $config = Config::get('wechat'); $app = Factory::payment($config); $response = $app->handlePaidNotify(function ($message, $fail) { // 根据$message中的参数进行验证和处理 // 验证通过后,处理订单状态等业务逻辑 return true; // 返回true表示处理成功 }); return $response; } }
<?php // route/route.php use think\facade\Route; Route::post('pay', 'WechatPayController/pay'); // 发起支付 Route::any('notify', 'WechatPayController/notify'); // 支付回调
参考原文:https://blog.csdn.net/weixin_42028285/article/details/93483574