微信支付例子

40 篇文章 0 订阅
3 篇文章 0 订阅

微信支付

微信支付,和我们支付宝支付大致都是一样的,只不过微信支付配置的时候很复杂,注意的细节:

开通商务号:

公众号,或者小程序,任意一个就可以,必须要有一个否则,无法申请支付,支付配置就要有appid如果公众号有,那么写公众号,有小程序就有小程序。

支付必备:

  1. 商务号:

小程序,或公众号任意一个即可。

  1. Appid

也就是商务号的id

上面两种情况我们如果都没有那么我们可以进行借权,但是借权

授权问题:

在登录小程序或者公众号的时候,有的会提示你,要获取你的账户信息,你是否允许,然后它提示你你点击允许,那么他可以获取你的头像和账户信息,有的不用你点击直接进去的,那么他就是静默授权,他获取不到你的头像,和名字,其他内容可以获取的到。

  1. 商务平台,连续交易90天

切忌不能刷单,不能用一个账号去刷,换着账号去刷,如果一天没有,从新开始

  1. 支付需要证书,证书两年过期,过期后不能使用,使用支付失败。

  1. 微信的支付单位是分

  1. 支付交易类型,有h5,小程序,公众号等。

    1. 支付的流程分析

先说一下支付的流程再说配置问题。

H5流程:

点击下单->后台将订单插入数据库->将订单号、商品名称、价钱(*100,因为他是一分)、appid、商户号、随机字符串、回调url、交易类型,传给微信支付->支付判断->支付成功->同步、异步返回信息->更改订单状态->给腾讯返回的信息(腾讯的订单信息)。

    1. 代码实例
<?php
// +----------------------------------------------------------------------
// | ******微信支付
// +----------------------------------------------------------------------
namespace app\api\controller;

use think\Controller;
use  think\DB;


class Wxpay extends Common
{

    //微信支付
    public function index()
    {

        //接收用户下单信息
        $goodsname                = input('goodsname');//商品名称
        $data['goodsid']          = input('goodsid');//商品id
        $data['buy_number_count'] = input('buy_number_count');//购买数量
        $data['total_price']      = input('total_price');//商品价格
        $data['add_time']         = time();//下单时间
        $data['phone']            = input('phone');//用户手机号
        $data['username']         = input('username');//用户姓名
        $data['address']          = input('address');//收货地址
        $data['userid']           = input('userid');//用户id
        if (input('goodstype')) {
            $data['goodstype'] = input('goodstype');//商品类型
        }

        $user = Db::name('user')->where(array('id' => $data['userid']))->field('openid')->find();//获取当前用户openID/这个我们登录的时候都存在了


        //发起微信支付,调用统一下单支付接口
        $fee          = $data['total_price'];//支付金额
        $appid        = '****************';//appid.如果是公众号 就是公众号的appid
        $body         = $goodsname;
        $mch_id       = '*******************';  //商户号
        $nonce_str    = $this->nonce_str();//随机字符串
        $notify_url   = '域名/api/wxpay/notifyurl'; //回调的url
        $openid       = $user['openid'];
        $time         = time();
        $year         = date('Y', $time);
        $rand         = rand(000000000, 999999999);
        $out_trade_no = $year . $rand;//订单号

        //$out_trade_no = $this->order_number($openid);//商户订单号
        $spbill_create_ip = $_SERVER["REMOTE_ADDR"];//服务器的ip;
        $total_fee        = $fee * 100;// 微信支付单位是分,所以这里需要*100
        $trade_type       = 'JSAPI';//交易类型 默认

        $data['order_no'] = $out_trade_no;
        $order            = Db::name('order')->insert($data);


        //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
        $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->xml($xml);//全要大写

        //print_r($array);
        //统一下单请求成功回调前端支付参数
        if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
            $time             = time();
            $tmp              = [];//临时数组用于签名
            $tmp['appId']     = $appid;
            $tmp['nonceStr']  = $nonce_str;
            $tmp['package']   = 'prepay_id=' . $array['PREPAY_ID'];
            $tmp['signType']  = 'MD5';
            $tmp['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 参数值
            $data['paySign']      = $this->sign($tmp);//签名
            $data['out_trade_no'] = $out_trade_no;


        } else {
            $data['state']       = 0;
            $data['text']        = "错误";
            $data['RETURN_CODE'] = $array['RETURN_CODE'];
            $data['RETURN_MSG']  = $array['RETURN_MSG'];
        }


        echo json_encode($data);
    }


    //随机32位字符串
    private function nonce_str()
    {
        $result = '';
        $str    = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
        for ($i = 0; $i < 32; $i++) {
            $result .= $str[rand(0, 48)];
        }
        return $result;
    }


    //生成订单号
    private function order_number($openid)
    {
        //date('Ymd',time()).time().rand(10,99);//18位
        return md5($openid . time() . rand(10, 99));//32位
    }


    //签名 $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
        $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 xml($xml)
    {
        $p = xml_parser_create();
        xml_parse_into_struct($p, $xml, $vals, $index);
        xml_parser_free($p);
        $data = [];
        foreach ($index as $key => $value) {
            if ($key == 'xml' || $key == 'XML') continue;
            $tag        = $vals[$value[0]]['tag'];
            $value      = $vals[$value[0]]['value'];
            $data[$tag] = $value;
        }
        return $data;
    }

    //支付回调接口
    public function notifyurl()
    {

        $res_xml = file_get_contents("php://input");
        libxml_disable_entity_loader(true);
        $ret               = json_decode(json_encode(simplexml_load_string($res_xml, 'simpleXMLElement', LIBXML_NOCDATA)), true);
        $data              = array();
        $data['order_sn']  = $ret['out_trade_no'];
        $data['trade_no']  = $ret['transaction_id'];
        $data['total_fee'] = $ret['total_fee'];

        $check_info = DB::name('order')->where(array('order_no' => $data['order_sn']))->find();
        if (!$check_info) {
            echo json_encode(array('state' => 1, 'msg' => '订单信息错误...'));
        }


        $up             = array();
        $up['status']   = 1;
        $up['pay_time'] = time();
        $res            = DB::name('order')->where(array('order_no' => $data['order_sn']))->update($up);//更新订单状态

        //支付成功升级等级
        if ($user['status'] == 0) {
            $device = DB::name('terminus')->where('userid', $check_info['userid'])->count();//查询用户名下终端机具

            $where['status']   = 1;
            $where['upd_time'] = time();
            if ($device >= 10) {
                $userdata = DB::name('user')->where(['id' => $check_info['userid']])->update($where);//更新当前用户等级为VIP
                if ($userdata) {
                    echo json_encode(array('state' => 1, 'msg' => '等级更新成功'));
                    exit;
                } else {
                    echo json_encode(array('state' => 2, 'msg' => '等级更新失败'));
                    exit;
                }
            }
        }

        //$result = $this->orderhandle($data);
        if ($res) {
            //将信息返回给腾讯一次
            $xml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg>";
            $xml .= "</xml>";
            echo $xml;
        }
    }


} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值