tp5.1 WeChat jsapi payment

The official account directly evokes WeChat payment

1. Explanation of the payment authorization directory:
1-1. The address of the page where the merchant finally requests to pull up the WeChat payment cash register is called the "payment directory", for example: https://www.weixin.com/pay.php.
1-2. The merchant’s actual payment directory must be consistent with the one set on the WeChat Pay merchant platform, otherwise it will report an error “The URL of the current page is not registered:” 2.
Log in to the WeChat Pay merchant platform (pay.weixin.qq.com) –> Product Center –> Development Configuration, usually takes effect within 5 minutes after setting.
3. Description of payment authorization directory verification rules:
3-1. If the payment authorization directory is set as a top-level domain name (for example: https://www.weixin.com/), then only the top-level domain name will be verified, and the suffix will not be verified;
3 -2. If the payment authorization directory is set to a multi-level directory, full matching will be performed. For example, if the payment authorization directory is set to https://www.weixin.com/abc/123/, the actual request page directory cannot be https:/ /www.weixin.com/abc/, also cannot be https://www.weixin.com/abc/123/pay/, must be https://www.weixin.com/abc/123/
4. Web page authorization When domain name
is developed for JSAPI payment, the user’s openid is required in the unified order interface, and to obtain openid, you need to set the domain name for obtaining openid on the public platform. Only the domain name that has been set is a valid domain name for obtaining openid, otherwise will fail to fetch. In Official Account Settings - Function Settings - Web Page Authorized Domain Name Settings. Note the download and location of the certificate.
5. Code block (personally prefer to put SDK in extend)

//控制器方法
<?php
namespace app\equipment\home;
use app\common\controller\Common;
use think\Db;
//use wxpay\wxpay as wxpay;
use WxpayService\WxpayService;

class Pay extends Common
{
    
    
	//获取支付参数
	//@param  mchid 微信支付商户号
	//@param  appid 微信支付申请对应的公众号的APPID
	//@param  appKey 微信支付申请对应的公众号的APP Key
	//@param  apiKey 微信支付API密钥
    public function salepay()
    {
    
    
        $data=$this->set_order($_POST);//创建订单
        if($data){
    
    
            header('Content-type:text/html; Charset=utf-8');
            $mchid = '';          //微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送
            $appid = '';  //微信支付申请对应的公众号的APPID
            $appKey = '';   //微信支付申请对应的公众号的APP Key
            $apiKey = '';   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥
            //①、获取用户openid
            $wxPay = new WxpayService($mchid,$appid,$appKey,$apiKey);
            $openId=session('openid');
            if(!$openId) exit('获取openid失败');
            //②、统一下单
            $outTradeNo = $data['order_no'];//你自己的商品订单号
            $payAmount = $data['amount'];          //付款金额,单位:元
            $orderName = '设备购买';    //订单标题
            $notifyUrl = 'http://域名/euipment/pay/setstatus/';     //付款成功后的回调地址(不要有问号)
            $payTime = time();      //付款时间
            $jsApiParameters = $wxPay->createJsBizPackage($openId,$payAmount,$outTradeNo,$orderName,$notifyUrl,$payTime);
            $jsApiParameters = json_encode($jsApiParameters);
            $array 	 = json_decode($jsApiParameters,true);
            $array['order_id']=$outTradeNo;
//            $array['code']=1;
            return $array;
        }

    }

    //创建订单
    public function set_order($info)
    {
    
    
        $openid=session('openid');
        $uid=Db::name('user')->where("openid",$openid)->value('id');
            Db::startTrans();
            try {
    
    
                //提交数据到user_equipment
                $data1['uid'] = $uid;
                $data1['create_time'] = date('Y-m-d', time());
                $data1['order_no'] = order_number();
                $data1['equipment_id'] = $info['equipment_id'];
                $data1['amount'] = $info['amount'];
                $data1['add_id'] = $info['add_id'];
                $data1['number'] = $info['number'];
                $res = Db::name('user_equipment')->insert($data1);
                //购买也要入购买表
                $data['uid'] = $uid;
                $data['sales_volume'] = $info['amount'];
                $data['equipment_id'] = $info['equipment_id'];
                $data['number'] = $info['number'];
                $data['add_id'] = $info['add_id'];
                $data['note'] = $info['note'];
                $data['create_time'] = time();
                $data['sale_no'] = $data1['order_no'];
                $data['pay_time'] = time();
                $res1 = Db::name('sale')->insert($data);
                Db::commit();
            }catch (\Exception $e) {
    
    
                // 回滚事务
                Db::rollback();
            }
            if($res && $res1){
    
    
                return $data1;
            }else{
    
    
                return 0;
            }

    }

    //支付成功后修改订单状态
    public function setstatus()
    {
    
    
        $order=$_POST['order_no'];
        $res=Db::name('user_equipment')->where('order_no',$order)->update(['order_status'=>2]);
        if($res){
    
    
            return $this->success('修改成功','',1);
        }else{
    
    
            return $this->error('修改失败','',0);
        }

    }
}

//Introduced file file location extend/WxpayService/WxpayService

<?php
namespace WxpayService;

class WxpayService
{
    
    
    protected $mchid;
    protected $appid;
    protected $appKey;
    protected $apiKey;
    public $data = null;
    public function __construct($mchid, $appid, $appKey,$key)
    {
    
    
        $this->mchid = $mchid; //https://pay.weixin.qq.com 产品中心-开发配置-商户号
        $this->appid = $appid; //微信支付申请对应的公众号的APPID
        $this->appKey = $appKey; //微信支付申请对应的公众号的APP Key
        $this->apiKey = $key;   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥
    }
    /**
     * 通过跳转获取用户的openid,跳转流程如下:
     * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
     * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
     * @return 用户的openid
     */
    public function GetOpenid()
    {
    
    


        //通过code获得openid
        if (!isset($_GET['code'])){
    
    
            return $_SERVER;
            //触发微信返回code码
            $scheme = $_SERVER['HTTPS']=='on' ? 'https://' : 'http://';
            $uri = $_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING'];
            if($_SERVER['REQUEST_URI']) $uri = $_SERVER['REQUEST_URI'];
            $baseUrl = urlencode($scheme.$_SERVER['HTTP_HOST'].$uri);
            $url = $this->__CreateOauthUrlForCode($baseUrl);
            Header("Location: $url");
            exit();
        } else {
    
    
            //获取code码,以获取openid
            $code = $_GET['code'];
            $openid = $this->getOpenidFromMp($code);
            return $openid;
        }
    }
    /**
     * 通过code从工作平台获取openid机器access_token
     * @param string $code 微信跳转回来带上的code
     * @return openid
     */
    public function GetOpenidFromMp($code)
    {
    
    
        $url = $this->__CreateOauthUrlForOpenid($code);
        $res = self::curlGet($url);
        //取出openid
        $data = json_decode($res,true);
        $this->data = $data;
        $openid = $data['openid'];
        return $openid;
    }
    /**
     * 构造获取open和access_toke的url地址
     * @param string $code,微信跳转带回的code
     * @return 请求的url
     */
    private function __CreateOauthUrlForOpenid($code)
    {
    
    
        $urlObj["appid"] = $this->appid;
        $urlObj["secret"] = $this->appKey;
        $urlObj["code"] = $code;
        $urlObj["grant_type"] = "authorization_code";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
    }
    /**
     * 构造获取code的url连接
     * @param string $redirectUrl 微信服务器回跳的url,需要url编码
     * @return 返回构造好的url
     */
    private function __CreateOauthUrlForCode($redirectUrl)
    {
    
    
        $urlObj["appid"] = $this->appid;
        $urlObj["redirect_uri"] = "$redirectUrl";
        $urlObj["response_type"] = "code";
        $urlObj["scope"] = "snsapi_base";
        $urlObj["state"] = "STATE"."#wechat_redirect";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
    }
    /**
     * 拼接签名字符串
     * @param array $urlObj
     * @return 返回已经拼接好的字符串
     */
    private function ToUrlParams($urlObj)
    {
    
    
        $buff = "";
        foreach ($urlObj as $k => $v)
        {
    
    
            if($k != "sign") $buff .= $k . "=" . $v . "&";
        }
        $buff = trim($buff, "&");
        return $buff;
    }
    /**
     * 统一下单
     * @param string $openid 调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid
     * @param float $totalFee 收款总费用 单位元
     * @param string $outTradeNo 唯一的订单号
     * @param string $orderName 订单名称
     * @param string $notifyUrl 支付结果通知url 不要有问号
     * @param string $timestamp 支付时间
     * @return string
     */
    public function createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp)
    {
    
    
        $config = array(
            'mch_id' => $this->mchid,
            'appid' => $this->appid,
            'key' => $this->apiKey,
        );

        //$orderName = iconv('GBK','UTF-8',$orderName);
        $unified = array(
            'appid' => $config['appid'],
            'attach' => 'pay',             //商家数据包,原样返回,如果填写中文,请注意转换为utf-8
            'body' => $orderName,
            'mch_id' => $config['mch_id'],
            'nonce_str' => self::createNonceStr(),
            'notify_url' => $notifyUrl,
            'openid' => $openid,            //rade_type=JSAPI,此参数必传
            'out_trade_no' => $outTradeNo,
            'spbill_create_ip' => '127.0.0.1',
            'total_fee' => intval($totalFee * 100),       //单位 转为分
            'trade_type' => 'JSAPI',
        );
        $unified['sign'] = self::getSign($unified, $config['key']);
        $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified));
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);

        if ($unifiedOrder === false) {
    
    
            die('parse xml error');
        }
        if ($unifiedOrder->return_code != 'SUCCESS') {
    
    
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
    
    
            die($unifiedOrder->err_code);
        }
        $arr = array(
            "appId" => $config['appid'],
            "timeStamp" => "$timestamp",        //这里是字符串的时间戳,不是int,所以需加引号
            "nonceStr" => self::createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => 'MD5',
        );
        $arr['paySign'] = self::getSign($arr, $config['key']);
        return $arr;
    }
    public static function curlGet($url = '', $options = array())
    {
    
    
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
    
    
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    public static function curlPost($url = '', $postData = '', $options = array())
    {
    
    
        if (is_array($postData)) {
    
    
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
    
    
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    public static function createNonceStr($length = 16)
    {
    
    
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
    
    
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    public static function arrayToXml($arr)
    {
    
    
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
    
    
            if (is_numeric($val)) {
    
    
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }
    public static function getSign($params, $key)
    {
    
    
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }
    protected static function formatQueryParaMap($paraMap, $urlEncode = false)
    {
    
    
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
    
    
            if (null != $v && "null" != $v) {
    
    
                if ($urlEncode) {
    
    
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
    
    
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

}
//页面订单提交部分
//订单提交
    function submit() {
    
    
        var eid=$("input[name='id']").val();
        var order_type=1;
        var order_status=1;
        var add_id=$.trim($("input[name='add_id']").val());
        var number=$("#n_reduce").siblings("#n_box").val();
        var amount=$("#heji").text();
        var note=$("input[name='note']").val();

        if(add_id == ''){
    
    
            alert('请添加地址');
            return false;
        }

        $.ajax({
    
    
                type:'post',
                url :'/index.php/equipment/pay/salepay',
                data:{
    
    "equipment_id":eid,'order_type':order_type,'order_status':order_status,'add_id':add_id,'number':number,
                        'amount':amount,'note':note},
                success:function(data){
    
    
                        console.log(data);
//订单创建成功返回支付参数和order_id便于前端唤起支付
                        pay(data.appId,data.timeStamp,data.nonceStr,data.package,data.paySign,data.order_id);
                },error:function(){
    
    
                    alert('创建订单失败!');
                }

        });

    }


    // 支付
    function pay(appid,time,nonceStr,prepay_id,paySign,order_id){
    
    
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
    
    
                "appId":appid,     		// 公众号名称,由商户传入
                "timeStamp":time,       // 时间戳,自1970年以来的秒数
                "nonceStr":nonceStr, 	// 随机串
                "package":prepay_id,    // 统一下单接口返回的prepay_id参数值
                "signType":"MD5",       // 微信签名方式:
                "paySign":paySign 		// 微信签名
            },function(res){
    
    
                console.log(res);
                if(res.err_msg == "get_brand_wcpay_request:ok" ){
    
    
                    $.ajax({
    
    
                        url:"/index.php/equipment/pay/setstatus",
                        type:"post",
                        data:{
    
    'order_no':order_id},
                        success:function (e) {
    
    

                            if(e.data==1){
    
    
                                alert('支付成功');
                                window.location.href='/index.php/user/index/order?type=2'
                            }else{
    
    
                                alert('支付失败')
                            }

                        }
                    })
                   // window.location.href = '';
                }
            });
    }

Mini Program WeChat Pay

Only the interface part is shown
, and the relevant configurations should not be missing. Check the relevant development documents for configuration and
directly upload the code

   //提交订单
    public function order()
    {
    
    
        $token=input('post.token');
        $res=checkToken($token);
        if($res ==90001) {
    
     //验证token成功
           $input=input('post.');
               $res1=$this->setOrder($input);
               if ($res1){
    
    
                   $appid=config('base.web_appid');//APPID
                   $openid=Db::name('user')->where("token",$token)->value('openid');
                   $mch_id=config('base.wev_mch_id');//商户号
                   $key=config('base.web_appsecret');
                   $apiKey=config('base.web_apiKey');
                   $out_trade_no=$res1['order_id'];
                   $body='支付测试';
                   $total_fee=$res1['amount'];
                   $notify_url = 'http://域名/xxx/xxx/xxx/notify';
                   $payTime=time();
                   $wxPay = new WxpayService($mch_id,$appid,$key,$apiKey);
                   $jsApiParameters = $wxPay->createJsBizPackage($openid,$total_fee,$out_trade_no,$body,$notify_url,$payTime);
                   $jsApiParameters = json_encode($jsApiParameters);
                   $array 	 = json_decode($jsApiParameters,true);
                   $array['order_id']=$out_trade_no;
                   $data['code']=1;
                   $data['msg']='订单创建成功';
                   $data['date']=$array;
                   return json($data);
               }else{
    
    
                   $data['code']=0;
                   $data['msg']='订单创建失败';
                   $data['date']=null;
                   return json($data);
               }

        }else if($res == 90002){
    
    
            $data['code']=2;
            $data['msg']='token验证出错';
            $data['date']=null;
            return json($data);
        }else if($res == 90003){
    
    
            $data['code']=3;
            $data['msg']='token超时,请重新登录';
            $data['date']=null;
            return json($data);
        }

    }

    //创建订单--走支付
    public function setOrder($arr)
    {
    
    
        Db::startTrans();
        try {
    
    
        $info['order_id']=order_number();
        $info['uid']=token_to_uid($arr['token']);
        $info['package_id']=$arr['package_id'];
        $info['house_id']=package_to_house($arr['package_id']);
        $info['number']=$arr['number'];
        $info['price']=$arr['price'];
        $info['amount']=$arr['amount'];
        $info['integral']=$arr['integral'];//购买套餐可获积分
        $info['coupon_id']=$arr['coupon_id'];
        $info['point']=$arr['point'];//直营店消费的积分数
        $info['tel']=$arr['tel'];
        $info['create_time']=time();

        $res=Db::name('order')->insert($info);
        $stock = Db::name('package')->where("id", $info['package_id'])->value('stock');
        $res1 = Db::name('package')->where("id", $info['package_id'])->update(['stock' => $stock - 1]);

            Db::commit();
            return $info;
        }catch (\Exception $e) {
    
    
            // 回滚事务
                Db::rollback();
                return 0;
        }

    }

`//支付回调
  public function notify(){
    
    
        $data = file_get_contents('php://input');
        $arr = $this -> xmlToArray($data);
            //判断返回状态
            if($arr['return_code'] == 'SUCCESS' || $arr['result_code'] == 'SUCCESS'){
    
    
                $status= Db::name('order')->where('order_id',$arr['out_trade_no'])->value('status');
                if ($status==1){
    
    
                    //修改订单状态
                    $res = Db::name('order')->where('order_id',$arr['out_trade_no'])->update(['status'=>2,'pay_time'=>time(),'transaction_id'=>$arr['transaction_id']]);
                    return '<xml> <return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
                }

        }
    }
  //将xml格式转换成数组
    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;
    }

``

Guess you like

Origin blog.csdn.net/zax_96/article/details/107033122
Recommended