php微信支付,APP支付

废话不多说,直接上干货,

<?php

// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: pl125 <xskjs888@163.com>
// +----------------------------------------------------------------------

namespace api\yikao\controller;

use api\portal\service\PortalPostService;
use api\user\model\UserFavoriteModel;
use api\user\model\UserLikeModel;
use cmf\controller\RestBaseController;
use api\portal\model\PortalPostModel;
use think\Db;
use think\db\Query;
use think\facade\Cache;
use think\facade\Request;

/*
 *      
 */

class WpayController extends RestBaseController
{

    
    protected $wechat_config;

    //https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
    public function __construct($wechat_config = [])
    {
        if(empty($wechat_config)){
            $wechat_config = [
                'appid'=>'w**2',//APPID
                'mch_id'=>'1**',//商户号
                'api_key'=>'CCW***gZ7',//支付秘钥
                'appsecret'=>'b9&&***',//APP秘钥
                'notify_url'=>'',//回调网址
            ];
        }
        $this->wechat_config = $wechat_config;

    }
    
  
    //支付陪练系统
    public function wpay(){
        //生成微信支付预订单信息
        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
        header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
        $data2 = Request::param();//过滤参数
        // dump($data2);die;
        $body = '商品';
        $total_fee = '1';
        $out_trade_no = 'PL'.date('YmdHis').rand(1000,9999);
        $attach = 'charge_order';
        $wechat_data = $this->wx_pay($body,$total_fee,$out_trade_no,$attach);

        $data = [
            'title'=>$body,
            'money'=>$total_fee,
            'order_no'=>$out_trade_no,
            'attach'=>$attach,
            'status'=>0,//未支付
        ];
        // dump($data);die;
        //写入数据库表信息
        Db::table('f_*')->insert($data);
       
        $this->relog('wxapp---'.json_encode($wechat_data));//日志
        if($wechat_data['code'] != 200){
            echo $wechat_data['msg'];die;
        } 
        
        $result = [ 'order_no'=>$out_trade_no , 'money'=>$total_fee, 'wechat_data'=>$wechat_data]; 
        return json_encode($result);
        // print_r($result);die;
    }



    //生成预支付订单
    public function wx_pay($body,$total_fee,$out_trade_no,$attach) {
        $nonce_str = $this->rand_code();        //调用随机字符串生成方法获取随机字符串
        $data['appid'] = $this->wechat_config['appid'];   //appid
        $data['mch_id'] = $this->wechat_config['mch_id'] ;        //商户号
        $data['body'] = $body;
        $data['spbill_create_ip'] = $this->get_client_ip();   //ip地址
        $data['total_fee'] = $total_fee;                         //金额
        $data['out_trade_no'] = $out_trade_no;    //商户订单号,不能重复
        $data['nonce_str'] = $nonce_str;                   //随机字符串
        $data['notify_url'] = $this->wechat_config['notify_url'];   //回调地址,用户接收支付后的通知,必须为能直接访问的网址,不能跟参数
        $data['trade_type'] = 'APP';      //支付方式
        $data['attach'] = $attach;      //商户携带订单的自定义数据
        //将参与签名的数据保存到数组  注意:以上几个参数是追加到$data中的,$data中应该同时包含开发文档中要求必填的剔除sign以外的所有数据

        $data['sign'] = self::getSign($data,$this->wechat_config['api_key']);        //获取签名

        $xml = self::ToXml($data);            //数组转xml
        //curl 传递给微信方
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //header("Content-type:text/xml");
        $ch = curl_init();
        curl_setopt($ch,CURLOPT_URL, $url);
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }    else    {
            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
        }
        //设置header
        curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_POST, TRUE);
        //传输文件
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if($data){

            curl_close($ch);
            //返回成功,将xml数据转换为数组.
            $re = self::FromXml($data);

            if($re['return_code'] != 'SUCCESS'){
                return [
                    'code'=>'201',
                    'msg'=>$re['return_msg']
                ];
            }
            else{
                //接收微信返回的数据,传给APP!
                $arr =array(
                    'prepayid' =>$re['prepay_id'],
                    'appid' => $this->wechat_config['appid'],
                    'partnerid' => $this->wechat_config['mch_id'],
                    'package' => 'Sign=WXPay',
                    'noncestr' => $nonce_str,
                    'timestamp' =>strval(time()),
                );
                //第二次生成签名
                $sign = self::getSign($arr,$this->wechat_config['api_key']);
                $arr['sign'] = $sign;
                $arr['code'] = '200';
                $arr['msg'] = '签名成功';
                return $arr;
            }
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            return [
                'code'=>'201',
                'msg'=>"curl出错,错误码:$error"
            ];

        }
    }




    //参数要组装成xml格式
    public static function ToXml($data = array()){
        if (!is_array($data) || count($data) <= 0) {
            return '数组异常';
        }

        $xml = "<xml>";
        foreach ($data as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }



    public static function FromXml($xml)
    {
        if(!$xml){
            echo "xml数据异常!";
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

    //生成随机字符串
    private function rand_code(){
        $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';//62个字符
        $str = str_shuffle($str);
        $str = substr($str,0,32);
        return  $str;
    }

    /*
    获取当前服务器的IP
    */
    private function get_client_ip(){
        if ($_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 = "unknown";
        }
        return $cip;
    }

    //生成签名
    public static function getSign($params,$api_key) {
        ksort($params);        //将参数数组按照参数名ASCII码从小到大排序
        foreach ($params as $key => $item) {
            if (!empty($item)) {         //剔除参数值为空的参数
                $newArr[] = $key.'='.$item;     // 整合新的参数数组
            }
        }

        $stringA = implode("&", $newArr);         //使用 & 符号连接参数
        $stringSignTemp = $stringA."&key=".$api_key;        //拼接key
        // key是在商户平台API安全里自己设置的
        $stringSignTemp = MD5($stringSignTemp);       //将字符串进行MD5加密
        $sign = strtoupper($stringSignTemp);      //将所有字符转换为大写
        return $sign;
    }
    
    // 微信支付回调
    public function wx_notifyAction(){
        
        //接收微信返回的数据数据,返回的xml格式
        $xmlData = file_get_contents('php://input');
        //dump(json_encode($xmlData));die;
        //将xml格式转换为数组
        $data = $this->FromXml($xmlData);
        //用日志记录检查数据是否接受成功,验证成功一次之后,可删除。
        $this->relog('wx---'.$xmlData);
        //为了防止假数据,验证签名是否和返回的一样。
        //记录一下,返回回来的签名,生成签名的时候,必须剔除sign字段。
        $sign = $data['sign'];
        unset($data['sign']);
        if($sign == $this->getSign($data,$this->wechat_config['api_key'])){
            //签名验证成功后,判断返回微信返回的
            $this->relog('wx---55'.$data['out_trade_no']);
                Db::name("app_user")->insert($shuju);
                echo '<xml>
                      <return_code><![CDATA[SUCCESS]]></return_code>
                      <return_msg><![CDATA[OK]]></return_msg>
                      </xml>';
                    exit();    
            // if($data['result_code'] == 'SUCCESS'){
            //     $this->relog('wxapp---44'.$data['result_code']);
            //     //根据返回的订单号做业务逻辑
            //     $res = false;
            //     if($data['attach'] == 'charge_order'){
                    
            //     }

            //     //处理完成之后,告诉微信成功结果!
            //     if($res == true){
            //         echo '<xml>
            //           <return_code><![CDATA[SUCCESS]]></return_code>
            //           <return_msg><![CDATA[OK]]></return_msg>
            //           </xml>';
            //         exit();
            //     }else{
            //         $file = fopen($file_name, 'a+');
            //         fwrite($file,date("Y-m-d H:i:s")."错误信息:数据修改失败,".json_encode($data).PHP_EOL);
            //     }
            // }
           
        }
        else{
            $file = fopen($file_name, 'a+');
            fwrite($file,date("Y-m-d H:i:s")."错误信息:签名验证失败,".json_encode($data).PHP_EOL);
        }

    }
    
    public function relog($word = '')
    {
        $word = is_array($word) ? var_export($word, 1) : $word;
        $fp = fopen( cmf_get_root().'temp/wx.txt', 'a+');
        flock($fp, LOCK_EX);
        fwrite($fp, '执行日期:' . strftime('%Y%m%d%H%M%S', time()) . "\n" . $word . "\n");
        flock($fp, LOCK_UN);
        fclose($fp);
    }

}

是不是很简单呀!

借鉴:php 微信支付V3 APP支付 - 一个人的孤独自白 - 博客园

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用 PHP 进行微信支付 V3 版本 App 支付的示例代码: ```php <?php // 设置请求参数 $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/app'; $merchant_id = 'your_merchant_id'; $serial_no = 'your_serial_no'; $private_key = 'your_private_key'; $appid = 'your_appid'; $out_trade_no = 'your_out_trade_no'; $description = 'your_description'; $total = 'your_total_amount'; $notify_url = 'your_notify_url'; // 生成签名 $time = time(); $nonce_str = uniqid(); $payload = array( 'mchid' => $merchant_id, 'appid' => $appid, 'description' => $description, 'out_trade_no' => $out_trade_no, 'notify_url' => $notify_url, 'amount' => array( 'total' => $total, 'currency' => 'CNY' ), 'time_expire' => date('c', strtotime('+2 hours')), 'nonce_str' => $nonce_str ); $payload_json = json_encode($payload, JSON_UNESCAPED_UNICODE); $sign_str = "POST\n/pay/transactions/app\n$time\n$nonce_str\n$payload_json\n"; $signature = openssl_sign($sign_str, $signature_raw, $private_key, OPENSSL_ALGO_SHA256); $signature_base64 = base64_encode($signature_raw); $header = array( 'User-Agent: Mozilla/5.0', 'Content-Type: application/json', 'Accept: application/json', 'Authorization: WECHATPAY2-SHA256-RSA2048 mchid="' . $merchant_id . '",serial_no="' . $serial_no . '",nonce_str="' . $nonce_str . '",timestamp="' . $time . '",signature="' . $signature_base64 . '"' ); // 发送请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload_json); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); $response = curl_exec($ch); $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // 处理响应 if ($http_status == 200) { $response_data = json_decode($response, true); // 处理响应数据 } else { // 处理错误 } ``` 在上述示例代码中,您需要将 $merchant_id、$serial_no、$private_key、$appid、$out_trade_no、$description、$total 和 $notify_url 替换为您自己的值。此外,您还需要根据微信支付的要求生成签名并将其添加到请求头中。 在处理响应时,您可以根据 API 的返回格式来处理 $response_data。如果请求失败,您可以根据 $http_status 处理错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xingxingwuxin

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值