search
HomeBackend DevelopmentPHP TutorialDetailed explanation of WeChat payment official account payment

This article mainly shares with you the detailed explanation of WeChat payment official account payment. With the popularity of WeChat payment, most products have developed their own official accounts, mini programs, etc. The marketing of products needs the support of payment. Recently, we have done I set up a WeChat official account to pay, and there are countless pitfalls. I will share it with you today, hoping it can help everyone.

You can take a look at the WeChat payment API documentation first

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_4

https://open.weixin.qq.com/cgi -bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317853&token=&lang=zh_CN

It is recommended to take a look at the developer documentation of WeChat first, although it is a bit confusing. . . .

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

Application scenarios

<br/>

Required jar package

<!-- 微信支付需要的jar包 -->
        <dependency>
            <groupId>xmlpull</groupId>
            <artifactId>xmlpull</artifactId>
            <version>1.1.3.1</version>
        </dependency>
        <dependency>
            <groupId>xpp3</groupId>
            <artifactId>xpp3</artifactId>
            <version>1.1.4c</version>
        </dependency>
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>fluent-hc</artifactId>
            <version>4.3.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.3.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient-cache</artifactId>
            <version>4.3.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.3.5</version>
        </dependency>

Parameters required for public account payment

public class WeixinMatchPayConfigure {
    /**
     * 域名  项目域名,根据需求自行配置
     */
    public static final String ROOTURL = WeixinPayConfigure.ROOTURL;
    /**
     * 订单域名  项目域名,根据需求自行配置
     */
    public static final String ORDER_ROOTURL = WeixinPayConfigure.ORDER_ROOTURL;
    /**
     * 赛事 域名  项目域名,根据需求自行配置
     */
    public static final String MATCHURL = "http://www.baidu.com";
    /**
     * 公共账号id 必填 (18位数↓)
     */
    public static final String APPID = WeixinPayConfigure.APPID;
    /**
     * 商户id  商户账号 必填
     */
    public static final String MCH_ID = "11111111";
    /**
     * 应用秘钥  必填(可在微信商户平台上查找)
     */
    public static final String APP_SECRET = "fd87878fsf87fsf8cvsd8";
    /**API秘钥*/ 必填(可在微信商户平台上查找)
    public static final String API_KEY = "fsdfn23482njdvjw23455555";
    /**
     * 统一下单URL  微信官方提供
     */
    public static final String PAY_UNIFIED_ORDER_API = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    /**
     * 微信公众号交易类型 (扫码支付类型:NATIVE,公众号支付类型:JSAPI)
     */
    public static final String TRADE_TYPE = "JSAPI";
    /**
     * 获取code的回调地址 你项目要展示的首页路径
     */
    public static final String REDIRECT_URI = "http://order.uxuexi.com/pay/apply.html";
    /**微信H5支付结果通知页*/
    public static final String NOTIFY_URL = ROOTURL + "/api/pay/weixin/notify.html";
    /**
     * 不弹出授权页面,直接跳转,只能获取用户openid
     */
    public static final String SCOPE = "snsapi_base";
    /**
     * 弹出授权页面,需要用户确认,可以获取用户的较多信息
     */
    public static final String USERINFOSCOPE = "snsapi_userinfo";
    /**
     * 获取微信code的url(登录授权)
     */
    public static final String GET_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
    /**
     * 获取用户的OpenId的url(必须先获得code之后调用)
     */
    public static final String GET_OPENID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
    /**
     * 微信支付成功之后的回调
     */
    public static final String NOTIFY_ACTIVITY_URL = WeixinPayConfigure.ORDER_ROOTURL + "/pay/wxnotify.json";
}

Get WeChat users openId

大致步骤:获取用户授权(获取code)------------->根据code获取openID(用户的基本信息)

1、配置授权域

这个则是在公众号登陆平台上面配置的↓


2、发起API请求获取用户授权

   URL:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

需要拼接三个参数:APPID、REDIRECT_URI、SCOPE,代码如下:

   //项目入口,如果这个项目是在公众号中,那么公众号菜单下面配置的就是这个接口的路径↓
    @At
    @Ok("jsp:match.entrance")
    @NotSso
    public Object entrance() {
        String codeUrl = WeiXinApiUrlUtil.getMatchUrl();
        return codeUrl;
    }

    public static String getMatchUrl() {
        String url = WeixinMatchPayConfigure.GET_CODE_URL;
        url = url.replace("APPID", urlEnodeUTF8(WeixinMatchPayConfigure.APPID));
        url = url.replace("REDIRECT_URI", WeixinMatchPayConfigure.REDIRECT_URI);
        url = url.replace("SCOPE", WeixinMatchPayConfigure.USERINFOSCOPE);
        return url;
    }
返回前端的是个Url路径,同个这个路径来获取微信用户授权,然后跳转我们自己的首页(REDIRECT_URI)
前端页面
<script type="text/javascript">
            $(document).ready(function(){ 
                            //其实这个时候跳转的URL它会跟着一连串属性,入下图 ↓
                    window.location.href=&#39;${obj}&#39;;
            });
</script>

3、微信用户openId是什么?

在微信用户关注公众号时,会对应的产生一个openId(openId:加密后的用户微信号),一个微信用户对应一个公众号产生的openId是唯一,当然,如果该微信号去关注另一个公众号所产生openID肯定和当前这个不一样的,OpenID 是最对『微信应用』的用户唯一值,同一个『微信开发者账号』下的不同应用中,使用同一个『微信用户』登录,此值会不一样,

废话不说,上代码↓

①、上文表明此接口请求带有参数code,那么需在这里接受code参数

 @At
    @Ok("jsp:match.apply")
    @NotSso
    public Object apply(@Param("code") String code) {
        return matchPayViewService.apply(code);
    }

②、获取openID放到session中去

public Object apply(String code) {
         //创建空map
        Map<String, Object> map = MapUtil.map();
         //获取session
        HttpSession session = Mvcs.getReq().getSession();
        //获取session中oppenID
        String oppendId = ConvertUtil.obj2str(session.getAttribute("oppendId"));
        //非空校验oppenID
        if (!Util.isEmpty(oppendId)) {
            map.put("isWeChat", "yes");
            return map;
        }
         //校验code是否为空,为空说明不是微信公众号支付
        if (Util.isEmpty(code)) {
            map.put("isWeChat", "no");
            return map;
        }
        //获取访问用户的token,(工具类1)
        UserInfoAccessTokenDt accessTokenDt = userInfoAccessTokenDtBaseService.getUserAccessToken(code);
        //获取微信用户信息,(工具类2)
        UserInfoDt userInfo = userInfoDtBaseService.getUserInfo(accessTokenDt);
        ExceptionUtil.checkEmpty(userInfo, "获取微信用户信息失败");
        map.put("userInfo", userInfo);
        int sessionInactive = 30 * 60;
        //把相关数据放到session中去
        session.setMaxInactiveInterval(sessionInactive);
        session.setAttribute("oppendId", userInfo.getOpenid());
        session.setAttribute("userInfo", userInfo);
        map.put("isWeChat", "yes");
        //获取当前用户
        map.put("userId", fetchUser.getCurrentUserId());
         //-----------------------------------------------------权限校验,可根据自己的项目进行业务操作
        map.put("isgxltUser", gXUnicomBusinessService.isPermission(fetchUser.getCurrentUserId()));
        return map;
    }

注:上面这些是获取微信用户授权、获取用户的基本信息,公众号支付需要用户的openID,所以。。。。。。

创建预支付Url

1、创建订单

①、此处不解释

    @At
    @Ok("jsp:match.createorder")
    @NotSso
    public Object createOrder(@Param("..") final OrderAddForm orderAddForm, final String gradeName) {
        return matchPayViewService.createOrder(orderAddForm, gradeName);
    }

②、创建订单

public Map<String, Object> createOrder(OrderAddForm orderAddForm, String gradeName) {
        ExceptionUtil.checkId(orderAddForm.getMatchId(), "赛事ID不能为空");
        Map<String, Object> map = MapUtil.map();
        orderAddForm.setCustomPrice(matchBaseService.getPrice(orderAddForm.getMatchId()).getPrice());
        OrderMatchEntity order = dbDao.insert(orderAddForm.toEntity());
        map.put("order", order);
        map.put("gradeName", gradeName);
                    //拼接预支付订单
        String result = sendReqGetPreOrder(order);
                    //转化为JsApiParam对象,(工具类3)
        JsApiParam jap = dowithWxReturn(result);
        map.put("jap", jap);
        return map;
    }

③、拼接预支付订单参数

    private String sendReqGetPreOrder(OrderMatchEntity order) {
        ExceptionUtil.checkEmpty(order.getId(), "订单id不能为空");
        Map<String, Object> params = MapUtil.map();
        params.put("appid", WeixinMatchPayConfigure.APPID);
        params.put("mch_id", WeixinMatchPayConfigure.MCH_ID);
        params.put("notify_url", WeixinMatchPayConfigure.NOTIFY_ACTIVITY_URL);
        params.put("trade_type", WeixinMatchPayConfigure.TRADE_TYPE);//单次订单为jsapi方式
        int randomNumLength = 32;
        params.put("nonce_str", RandomUtil.randomString(randomNumLength));
                   //获取openID
        params.put("openid", getWxUserInfoWithEx().getOpenid());
        String body = "赛事报名";
        params.put("body", body);
        params.put("out_trade_no", order.getId());
        long total_fee = AmountUtils.changeY2F(order.getCustomPrice());
        params.put("total_fee", total_fee);
        params.put("device_info", "WEB");
                    //加密签名,工具类(微信支付PC端文档中有)
        String sign = Signature.getSign(params, WeixinMatchPayConfigure.API_KEY);
        params.put("sign", sign);
                   //HttpRequest  工具类(微信支付PC端文档中有)
        return HttpRequest.sendPost(WeixinMatchPayConfigure.PAY_UNIFIED_ORDER_API, params);
    }  
        //获取微信标识
    private UserInfoDt getWxUserInfoWithEx() {
        Object userInfo = Mvcs.getReq().getSession().getAttribute("userInfo");
        if (Util.isEmpty(userInfo)) {
            throw ExceptionUtil.bEx("获取你的微信身份的标识失败请重新退出再次进入");
        }
        //类型转换
        return ConvertUtil.cast(userInfo, UserInfoDt.class);
    }

④、处理调用微信预支付订单的返回值

 private JsApiParam dowithWxReturn(String result) {
        //该类见(工具类3)
        JsApiParam jsApiParam = new JsApiParam();
        Map<String, Object> weixinPrepayInfo = MapUtil.map();
        try {
            //------------------解析XML(工具类:微信支付PC端文档中有)
            weixinPrepayInfo = XMLParser.getMapFromXML(result);
            String return_code = (String) weixinPrepayInfo.get("return_code");
            if ("SUCCESS".equals(return_code)) {
                String prepay_id = (String) weixinPrepayInfo.get("prepay_id");
                //给jsApiParam对象赋值
                jsApiParam.setPrepay_id(prepay_id);
                jsApiParam.setPackageInfo("prepay_id=" + prepay_id);
                jsApiParam.setPaySign(getJsApiPaySign(jsApiParam));
                return jsApiParam;
            } else {
                throw ExceptionUtil.bEx("预支付失败");
            }
        } catch (Exception e) {
            ExceptionUtil.bEx("调用微信预支付接口出错");
        }
        return jsApiParam;
    }

⑤、调用jsApiParam对象打回前台后,则需要调用微信内部的提供的js方法getBrandWCPayRequest

    function onBridgeReady(){
             //微信内部提供的js方法
             WeixinJSBridge.invoke(
                   &#39;getBrandWCPayRequest&#39;, {
                   "appId":"${obj.jap.appId}",     //公众号名称,由商户传入     
                   "timeStamp":"${obj.jap.timeStamp}",         //时间戳,自1970年以来的秒数     
                   "nonceStr":"${obj.jap.nonceStr}", //随机串     
                   "package":"${obj.jap.packageInfo}",     
                   "signType":"MD5",         //微信签名方式:     
                   "paySign":"${obj.jap.paySign}" //微信签名 
               },
               function(res){
                    // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
                       if (res.err_msg == "get_brand_wcpay_request:ok") {
                        //跳转到成功页面
                        window.location.href = "http://lannong.uxuexi.com/register/success.html";
                    } else if (res.err_msg == "get_brand_wcpay_request:cancel") {
                        WeixinJSBridge.call(&#39;closeWindow&#39;);
                    } else {
                    }
               }
           ); 
    }

⑥、调用⑤后页面则会弹出微信支付框,如图↓


支付成功

1、支付成功后则调用成功后的回调函数

    @At
    @Filters
    public void wxnotify() throws Exception {
        matchPayViewService.weChatPayViewService();
    }

2、签名校验

     public void weChatPayViewService() throws Exception {
        HttpServletRequest request = Mvcs.getReq();
        HttpServletResponse response = Mvcs.getResp();
        //获取微信响应的内容
        String responseString = getWeiXinResponseContent(request);
        PrintWriter out = response.getWriter();
        String resp = "";
        String signKey = WeixinPayConfigure.API_KEY;
        //------------------------------签名校验↓,(工具类:微信支付PC端文档中有)
        boolean verify = Signature.checkIsSignValidFromResponseString(responseString, signKey);
        if (!verify) {
            logger.error("签名验证失败");
            resp = "签名验证失败";
            out.write(resp);
            out.close();
            //签名失败直接返回
            return;
        }
        //解析xml
        Map<String, Object> map = XMLParser.getMapFromXML(responseString);
        String result_code = ConvertUtil.obj2str(map.get("result_code"));
        if (!"SUCCESS".equalsIgnoreCase(result_code)) {
            resp = PayCommonUtil.getResponseXML("ERROR", "ERROR");
            out.write(resp);
            out.close();
            //支付失败直接返回
            return;
        }
        //处理订单
        resp = handleOrder(map);
        out.write(resp);
        out.close();
    }
    //获取微信响应内容
    private String getWeiXinResponseContent(HttpServletRequest request) throws IOException,
            UnsupportedEncodingException {
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        //获取微信调用我们notify_url的返回信息
        String responseString = new String(outStream.toByteArray(), "utf-8");
        outStream.close();
        inStream.close();
        return responseString;
    }

3、处理订单,此处业务不再讲解,不懂得可以去看PC端微信支付文档

    @Aop("txDb")
    private String handleOrder(Map<String, Object> map) throws Exception {
        String resp = PayCommonUtil.getResponseXML("SUCCESS", "OK");
        String transaction_id = ConvertUtil.obj2str(map.get("transaction_id"));
        String time_end = ConvertUtil.obj2str(map.get("time_end"));
        String out_trade_no = (String) map.get("out_trade_no");
        if (Util.isEmpty(transaction_id) || Util.isEmpty(time_end) || Util.isEmpty(out_trade_no)) {
            resp = PayCommonUtil.getResponseXML("ERROR", "参数错误,微信支付订单号、支付完成时间、订单号均不能为空");
            return resp;
        }
        OrderMatchEntity order = dbDao.fetch(OrderMatchEntity.class, ConvertUtil.obj2long(out_trade_no));
        if (Util.isEmpty(order)) {
            resp = PayCommonUtil.getResponseXML("ERROR", "订单不存在");
            return resp;
        }
        int orderStatus = order.getStatus();
        if (OrderStatusEnum.FINISHED.intKey() == orderStatus) {
            return resp;
        }
        if (OrderStatusEnum.WAITING_PAY.intKey() == orderStatus) {
             //此处写你所需的业务即可
            //更新订单为完成状态
            //实际支付金额(分)
            //添加支付记录
        }
        return resp;
    }

4、公众号微信支付,支付后微信会返回三种状态,如图↓


那么,关于三种状态我们所需跳转的页面则可以在前台用js来实现

function(res){
    // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
    if (res.err_msg == "get_brand_wcpay_request:ok") {
         //跳转到成功页面
         window.location.href = "http://lannong.uxuexi.com/register/success.html";
       } else if (res.err_msg == "get_brand_wcpay_request:cancel") {
         WeixinJSBridge.call(&#39;closeWindow&#39;);
       } else {
     }
}

工具类

1、获取访问用户的token

@IocBean
public class UserInfoAccessTokenDtBaseService {
    /**
     * 通过code获取用户的openId
     * 
     * @param code 编号
     * 
     * @return 用户的openId
     */
    public UserInfoAccessTokenDt getUserAccessToken(String code) {
        ExceptionUtil.checkEmpty(code, "用户同意授权,获取的code不能为空");
        //获取用户openid的连接
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WeixinH5PayConfigure.APPID
                + "&secret=" + WeixinH5PayConfigure.APP_SECRET + "&code=" + code + "&grant_type=authorization_code";
        Response res = Http.get(url);
        String content = res.getContent();
        //----------------------------------从 JSON 字符串中,根据获取某种指定类型的 JSON 对象
        UserInfoAccessTokenDt accessTokenDt = JsonUtil.fromJson(content, UserInfoAccessTokenDt.class);
        return accessTokenDt;
    }
}

2、获取微信用户基本信息

@IocBean
public class UserInfoDtBaseService {
    /**
     * 获取用户信息
     * 
     * @param accessTokenDt 获取用户信息的token
     * 
     * @return 用户信息对象
     */
    public UserInfoDt getUserInfo(UserInfoAccessTokenDt accessTokenDt) {
        ExceptionUtil.checkEmpty(accessTokenDt, "访问用户的accessToken不能为空");
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessTokenDt.getAccess_token()
                + "&openid=" + accessTokenDt.getOpenid() + "&lang=zh_CN";
        Response res = Http.get(url);
        String content = res.getContent();
                    //------------------------------------- 从 JSON 字符串中,根据获取某种指定类型的 JSON 对象。↓
        UserInfoDt UserInfo = JsonUtil.fromJson(content, UserInfoDt.class);
        return UserInfo;
    }
}
@Data
public class UserInfoAccessTokenDt {
    //TODO(注释去这个链接下找:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html)
    private String access_token;
    private String expires_in;
    private String refresh_token;
    private String openid;
    private String scope;
    private String unionid;
}

3、微信公众号支付参数

@Data
public class JsApiParam {
    /**
     * 公众号appid
     */
    private String appId = WeixinH5PayConfigure.APPID;
    /**
     * 时间戳
     */
    private String timeStamp = System.currentTimeMillis() + "";
    /**
     * 随机字符串
     */
    private String nonceStr = RandomUtil.randIntString(32);
    /**
     * 签名方式
     */
    private String signType = "MD5";
    /**
     * 预支付id
     */
    private String packageInfo;
    /**
     * 支付签名
     */
    private String paySign;
    /**
     * 订单号
     */
    private String orderNo;
    /**
     * 微信预付单号
     */
    private String prepay_id;
}

           

The above is the detailed content of Detailed explanation of WeChat payment official account payment. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
The Continued Use of PHP: Reasons for Its EnduranceThe Continued Use of PHP: Reasons for Its EnduranceApr 19, 2025 am 12:23 AM

What’s still popular is the ease of use, flexibility and a strong ecosystem. 1) Ease of use and simple syntax make it the first choice for beginners. 2) Closely integrated with web development, excellent interaction with HTTP requests and database. 3) The huge ecosystem provides a wealth of tools and libraries. 4) Active community and open source nature adapts them to new needs and technology trends.

PHP and Python: Exploring Their Similarities and DifferencesPHP and Python: Exploring Their Similarities and DifferencesApr 19, 2025 am 12:21 AM

PHP and Python are both high-level programming languages ​​that are widely used in web development, data processing and automation tasks. 1.PHP is often used to build dynamic websites and content management systems, while Python is often used to build web frameworks and data science. 2.PHP uses echo to output content, Python uses print. 3. Both support object-oriented programming, but the syntax and keywords are different. 4. PHP supports weak type conversion, while Python is more stringent. 5. PHP performance optimization includes using OPcache and asynchronous programming, while Python uses cProfile and asynchronous programming.

PHP and Python: Different Paradigms ExplainedPHP and Python: Different Paradigms ExplainedApr 18, 2025 am 12:26 AM

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

PHP and Python: A Deep Dive into Their HistoryPHP and Python: A Deep Dive into Their HistoryApr 18, 2025 am 12:25 AM

PHP originated in 1994 and was developed by RasmusLerdorf. It was originally used to track website visitors and gradually evolved into a server-side scripting language and was widely used in web development. Python was developed by Guidovan Rossum in the late 1980s and was first released in 1991. It emphasizes code readability and simplicity, and is suitable for scientific computing, data analysis and other fields.

Choosing Between PHP and Python: A GuideChoosing Between PHP and Python: A GuideApr 18, 2025 am 12:24 AM

PHP is suitable for web development and rapid prototyping, and Python is suitable for data science and machine learning. 1.PHP is used for dynamic web development, with simple syntax and suitable for rapid development. 2. Python has concise syntax, is suitable for multiple fields, and has a strong library ecosystem.

PHP and Frameworks: Modernizing the LanguagePHP and Frameworks: Modernizing the LanguageApr 18, 2025 am 12:14 AM

PHP remains important in the modernization process because it supports a large number of websites and applications and adapts to development needs through frameworks. 1.PHP7 improves performance and introduces new features. 2. Modern frameworks such as Laravel, Symfony and CodeIgniter simplify development and improve code quality. 3. Performance optimization and best practices further improve application efficiency.

PHP's Impact: Web Development and BeyondPHP's Impact: Web Development and BeyondApr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

How does PHP type hinting work, including scalar types, return types, union types, and nullable types?How does PHP type hinting work, including scalar types, return types, union types, and nullable types?Apr 17, 2025 am 12:25 AM

PHP type prompts to improve code quality and readability. 1) Scalar type tips: Since PHP7.0, basic data types are allowed to be specified in function parameters, such as int, float, etc. 2) Return type prompt: Ensure the consistency of the function return value type. 3) Union type prompt: Since PHP8.0, multiple types are allowed to be specified in function parameters or return values. 4) Nullable type prompt: Allows to include null values ​​and handle functions that may return null values.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools