欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用微信小程序+JAVA實(shí)現(xiàn)微信支付的全過程

 更新時(shí)間:2024年08月17日 13:56:49   作者:z不像程序員的程序猿  
微信支付是一種在線支付解決方案,允許用戶通過微信內(nèi)的支付功能進(jìn)行付款,下面這篇文章主要給大家介紹了關(guān)于利用微信小程序+JAVA實(shí)現(xiàn)微信支付的相關(guān)資料,需要的朋友可以參考下

本文主要講的是小程序?qū)崿F(xiàn)微信支付功能,后臺(tái)采用JAVA。

一.準(zhǔn)備工作

1.小程序

2.微信商戶號(hào)

1.商戶號(hào)申請(qǐng)

這里對(duì)小程序的申請(qǐng)不做贅述。

如果沒有微信商戶號(hào)的同學(xué),點(diǎn)擊該鏈接https://pay.weixin.qq.com/,按照下屬步驟進(jìn)行商戶號(hào)申請(qǐng)。

掃碼之后點(diǎn)擊"成為商家",這里主要有個(gè)體工商戶和企業(yè),按照事實(shí)填寫,然后按照步驟填寫就行了。
主要需要營(yíng)業(yè)執(zhí)照,法人信息,公賬信息等。

2.微信商戶號(hào)關(guān)聯(lián)小程序

點(diǎn)擊"產(chǎn)品中心"的"開發(fā)配置",點(diǎn)擊"新增授權(quán)申請(qǐng)單"。

輸入你的小程序appid,點(diǎn)擊下一步。

然后到小程序后臺(tái)>微信支付>商戶號(hào)管理里,會(huì)出現(xiàn)一個(gè)申請(qǐng)單,點(diǎn)擊“查看”。

點(diǎn)擊確認(rèn)綁定,這樣你的商戶號(hào)就與小程序進(jìn)行綁定了。

二.代碼編寫

1.小程序

小程序這塊主要是調(diào)用一下后臺(tái)接口獲取參數(shù),然后通過參數(shù)拉起微信支付。

orderPay(payInfo){
  let that = this
  wx.requestPayment({
    'timeStamp': payInfo.timeStamp,
    'nonceStr': payInfo.nonceStr,
    'package': payInfo.package,
    'signType': payInfo.signType,
    'paySign': payInfo.paySign,
    'success': function (res) {
		// 支付成功的回調(diào)
    },
    'fail': function (res) {
      console.log(JSON.stringify(res));
      wx.showToast({title: '支付失敗', icon: 'none',duration: 2000,mask: true})
    }
  })
},

這里的payInfo就是從后臺(tái)接口獲取的支付參數(shù),通過wx.requestPayment就可以拉起微信支付了。具體的參數(shù)信息在下面會(huì)進(jìn)行講解。

2.服務(wù)端(JAVA)

服務(wù)端這邊主要是三個(gè)接口:

1.提交支付訂單

這個(gè)主要是為了獲取提交支付訂單,獲取前端拉起支付的參數(shù)。

2.微信支付回調(diào)

當(dāng)你小程序拉起支付并且成功支付后,會(huì)將支付結(jié)果回調(diào)到這個(gè)接口

3.支付訂單查詢

你也可以主動(dòng)通過訂單號(hào)查詢支付訂單狀態(tài)

下面是我的代碼,包含了我的業(yè)務(wù)代碼,大家將就著看吧

controller:

import com.smart.iot.gmt.app.bean.CommonReponse;
import com.smart.iot.gmt.app.constant.ResponseContant;
import com.smart.iot.gmt.app.constant.SessionKeyConstants;
import com.smart.iot.gmt.app.request.wechatPay.PaymentRequest;
import com.smart.iot.gmt.app.request.wechatPay.QueryPayOrderRequest;
import com.smart.iot.gmt.app.response.wechat.WechatPaymentResponse;
import com.smart.iot.gmt.app.response.wechat.WechatQueryPayOrderResponse;
import com.smart.iot.gmt.app.service.CommonService;
import com.smart.iot.gmt.app.service.pay.wechat.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Slf4j
@RestController
public class WxPayController {

    @Autowired
    private WxPayService service;
    @Autowired
    private CommonService commonService;

    /**
     *
     * @author Rick chou
     * @date 2024/7/18 15:33
     * 提交支付
     *
     */
    @PostMapping("/payment")
    public CommonReponse payment(@RequestBody PaymentRequest paymentRequest) {
        Integer price = paymentRequest.getPrice();
        String orderId = paymentRequest.getOrderId();
        Map<String, Object> result = service.payment(price, orderId, userId);
        CommonReponse commonResponse = commonService.getCommonResponse(ResponseContant.SUCCESS_CODE, ResponseContant.SUCCESS, result);
        return new WechatPaymentResponse(commonResponse,result);
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/15 16:57
     * 微信支付回調(diào)
     *
     */
    @PostMapping("/payNotify")
    public void payNotify(HttpServletRequest request) throws Exception {
        service.payNotify(request);
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/15 16:57
     * 支付查詢
     *
     */
    @PostMapping("/queryPayOrder")
    public CommonReponse queryPayOrder(@RequestBody QueryPayOrderRequest request) {
        Map<String, Object> result = service.queryPayOrder(request);
        CommonReponse commonResponse = commonService.getCommonResponse(ResponseContant.SUCCESS_CODE, ResponseContant.SUCCESS, result);
        return new WechatQueryPayOrderResponse(commonResponse,result);
    }
}

service:

import com.alibaba.fastjson.JSON;
import com.smart.iot.constant.RedisKeys;
import com.smart.iot.device.dto.LockNotifyMessageDTO;
import com.smart.iot.device.service.DeviceRedisCacheService;
import com.smart.iot.gmt.app.annotation.SpringUtil;
import com.smart.iot.gmt.app.bo.*;
import com.smart.iot.gmt.app.entity.MemberOrderDetailEntity;
import com.smart.iot.gmt.app.enums.MemberOrderStateEnum;
import com.smart.iot.gmt.app.request.wechatPay.QueryPayOrderRequest;
import com.smart.iot.gmt.app.service.LockNotifyMessageService;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.util.Map;

@Slf4j
@Service
public class WxPayService {

    public Map<String, Object> payment(Integer price, String orderId, String userId){
        Map<String, Object> result = WechatPayBo.payment(price, orderId, userId);
        return result;
    }

    @Transactional
    public void payNotify(HttpServletRequest request) throws Exception {
        Transaction parse = WechatPayBo.payNotify(request);
        updateAccountDetail(parse,false);
    }

    @Transactional
    public Map<String,Object> queryPayOrder(QueryPayOrderRequest request) {
        String orderId = request.getOrderId();
        Transaction parse = WechatPayBo.queryPayOrder(orderId);
        return updateAccountDetail(parse,true);
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 11:03
     * 支付回調(diào)處理
     * 1.更新訂單狀態(tài)
     * 2.添加支付記錄
     * 3.通知小程序
     *
     */
    public Map<String,Object> updateAccountDetail(Transaction parse, boolean active) {
        String orderId = parse.getOutTradeNo();
        Transaction.TradeStateEnum tradeState = parse.getTradeState();
        if(tradeState==Transaction.TradeStateEnum.SUCCESS) {
            if(OrderBo.check(orderId).getState() == MemberOrderStateEnum.IN_PROGRESS.code) {
                OrderBo order = this.updateOrder(orderId);
                this.renewMember(orderId);
                this.saveRecord(parse, order.getUserId());
            }
        }
        if(active){
            return JSON.parseObject(buildParse(parse),Map.class);
        }else{
            this.payNoticeMessage(parse,orderId);
        }
        return null;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/19 15:31
     * 更新訂單狀態(tài)
     *
     */
    private OrderBo updateOrder(String orderId){
        OrderBo order = OrderBo.check(orderId);
        order.finish();
        String key = RedisKeys.ADD_ORDER_PAY_TIME_PREFIX + orderId;
        SpringUtil.getBean(DeviceRedisCacheService.class).delete(key);
        return order;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/19 15:32
     * 更新會(huì)員時(shí)間
     *
     */
    private void renewMember(String orderId){
        MemberOrderDetailEntity orderDetail = OrderDetailBo.getByOrderId(orderId);
        UserMemberBo.renew(orderDetail);
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/19 15:33
     * 保存支付記錄
     *
     */
    private void saveRecord(Transaction parse,String userId){
        String orderId = parse.getOutTradeNo();
        Integer amount = parse.getAmount().getTotal();
        String tradeType = parse.getTradeType().name();
        PayRecordBo.create(userId,orderId,amount,tradeType);
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/19 15:38
     * 將支付結(jié)果下發(fā)小程序
     *
     */
    private void payNoticeMessage(Transaction parse,String orderId){
        MemberOrderDetailEntity detail = OrderDetailBo.getByOrderId(orderId);
        LockNotifyMessageService service = SpringUtil.getBean(LockNotifyMessageService.class);
        LockNotifyMessageDTO dto = new LockNotifyMessageDTO();
        dto.setLockId(detail.getDeviceId());
        dto.setMessageParams(buildParse(parse));
        service.dealPayResultNotifyMessage(dto);
    }

    private String buildParse(Transaction parse){
        parse.setMchid(null);
        parse.setAppid(null);
        parse.setBankType(null);
        parse.setBankType(null);
        parse.setAttach(null);
        return JSON.toJSONString(parse);
    }
}

bo:

import com.smart.iot.gmt.app.annotation.SpringUtil;
import com.smart.iot.gmt.app.entity.PayRecordEntity;
import com.smart.iot.gmt.app.service.pay.wechat.PayInfoConfig;
import com.smart.iot.gmt.app.service.pay.wechat.WXPayUtil;
import com.smart.iot.util.StringUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.wechat.pay.java.core.http.Constant.*;

/**
 *
 * @author Rick chou
 * @date 2024/7/16 9:10
 * 微信支付BO
 *
 */
@Slf4j
@Component
public class WechatPayBo extends PayRecordEntity {

    private static PayInfoConfig getConfig(){
        PayInfoConfig payInfoConfig = SpringUtil.getBean(PayInfoConfig.class);
        return payInfoConfig;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 9:35
     * 構(gòu)建支付請(qǐng)求SERVICE
     *
     */
    public static JsapiService getService(){
        PayInfoConfig payInfoConfig = getConfig();
        Config config = new RSAAutoCertificateConfig.Builder()
            .merchantId(payInfoConfig.getMchId())
            .privateKeyFromPath(payInfoConfig.getKeyPath())
            .merchantSerialNumber(payInfoConfig.getMchSerialNo())
            .apiV3Key(payInfoConfig.getApiKey())
            .build();
        JsapiService service = new JsapiService.Builder().config(config).build();
        return service;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 10:31
     * 構(gòu)造NOTIFY_CONFIG
     *
     */
    private static NotificationConfig buildNotifyConfig(){
        PayInfoConfig payInfoConfig = getConfig();
        NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                .merchantId(payInfoConfig.getMchId())
                .privateKeyFromPath(payInfoConfig.getKeyPath())
                .merchantSerialNumber(payInfoConfig.getMchSerialNo())
                .apiV3Key(payInfoConfig.getApiKey())
                .build();
        return config;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 9:35
     * 構(gòu)建支付請(qǐng)求參數(shù)
     *
     */
    private static PrepayRequest buildParam(Integer price, String orderId, String userId){
        PayInfoConfig payInfoConfig = getConfig();
        PrepayRequest prepayRequest = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(price);
        prepayRequest.setAmount(amount);
        prepayRequest.setAppid(payInfoConfig.getAppId());
        prepayRequest.setMchid(payInfoConfig.getMchId());
        prepayRequest.setNotifyUrl(payInfoConfig.getNotifyUrl());				// 回調(diào)接口地址
        prepayRequest.setDescription("微信支付");
        prepayRequest.setOutTradeNo(orderId);       // 訂單號(hào)
        prepayRequest.setAttach("member");                                     // 訂單類型(回調(diào)時(shí)可根據(jù)這個(gè)數(shù)據(jù)辨別訂單類型或其他)

        //根據(jù)token拿到openid,指定該預(yù)支付訂單的支付者身份
        Payer payer = new Payer();
        payer.setOpenid(WeixinUserBo.getOpenId(userId));
        prepayRequest.setPayer(payer);
        return prepayRequest;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 9:53
     * 解析支付結(jié)果
     *
     */
    private static Map<String,Object> parsePay(PrepayResponse response){
        PayInfoConfig payInfoConfig = getConfig();
        Map<String, Object> params = new HashMap<>();
        Long timeStamp = System.currentTimeMillis() / 1000;
        String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        String signatureStr = Stream.of(
                payInfoConfig.getAppId(),
                String.valueOf(timeStamp),
                substring,
                "prepay_id=" + response.getPrepayId()
        ).collect(Collectors.joining("\n", "", "\n"));
        String sign = WXPayUtil.getSign(signatureStr, payInfoConfig.getKeyPath());
        params.put("timeStamp", String.valueOf(timeStamp));
        params.put("nonceStr", substring);
        params.put("paySign", sign);
        params.put("signType", "RSA");
        params.put("package", "prepay_id=" + response.getPrepayId());
        return params;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 10:33
     * 解析回調(diào)結(jié)果
     *
     */
    private static RequestParam parseNotify(HttpServletRequest request)throws IOException {
        String data = StringUtil.getStringForInput(request.getInputStream());
        String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
        String nonce = request.getHeader(WECHAT_PAY_NONCE);
        String signType = request.getHeader("Wechatpay-Signature-Type");
        String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
        String signature = request.getHeader(WECHAT_PAY_SIGNATURE);

        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(serialNo)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                .signType(signType)         // 若未設(shè)置signType,默認(rèn)值為 WECHATPAY2-SHA256-RSA2048
                .body(data)
                .build();
        return requestParam;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 9:47
     * 調(diào)起支付
     *
     */
    public static Map<String, Object> payment(Integer price, String orderId, String userId){
        JsapiService service = getService();
        PrepayRequest prepayRequest = buildParam(price, orderId, userId);
        PrepayResponse response = service.prepay(prepayRequest);
        Map<String, Object> result = parsePay(response);
        result.put("orderId",orderId);
        return result;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 10:16
     * 支付回調(diào)
     *
     */
    public static Transaction payNotify(HttpServletRequest request) throws Exception {
        NotificationConfig config = buildNotifyConfig();
        NotificationParser parser = new NotificationParser(config);
        RequestParam requestParam = parseNotify(request);
        Transaction parse = null;
        try {
             parse = parser.parse(requestParam, Transaction.class);
        }catch (ValidationException e){
            log.error("sign verification failed", e);
        }
        return parse;
    }

    /**
     *
     * @author Rick chou
     * @date 2024/7/16 11:17
     * 查詢訂單
     *
     */
    public static Transaction queryPayOrder(String orderId) {
        PayInfoConfig payInfoConfig = getConfig();
        JsapiService service = getService();
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(payInfoConfig.getMchId());
        queryRequest.setOutTradeNo(orderId);
        Transaction parse = null;
        try {
            parse = service.queryOrderByOutTradeNo(queryRequest);
        }catch (ServiceException e){
            log.info("code=[%s], message=[%s]\n", e.getErrorCode(), e.getErrorMessage());
            log.info("reponse body=[%s]\n", e.getResponseBody());
        }
        return parse;
    }
}

PayInfoConfig

import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@ToString
@Component
@ConfigurationProperties(prefix = "wx")
public class PayInfoConfig {

    //小程序appid
    private String appId;
    //商戶號(hào)
    private String mchId;
    //證書序列號(hào)
    private String mchSerialNo;
    //小程序秘鑰
    private String appSecret;
    //api秘鑰
    private String apiKey;
    //回調(diào)接口地址
    private String notifyUrl;
    //證書地址
    private String keyPath;
}

上述的PayInfoConfig中的參數(shù)第二、三、五、七個(gè)參數(shù)去商戶號(hào)后臺(tái)獲取。

三.補(bǔ)充說明

在實(shí)際的支付開發(fā)中需要注意一些比較重要的點(diǎn),假設(shè)你現(xiàn)在做的是一個(gè)會(huì)員開通功能。

1.在你點(diǎn)擊開通的時(shí)候,你需要做的肯定是調(diào)用你自己的后臺(tái)業(yè)務(wù)接口生成一個(gè)會(huì)員訂單,同時(shí)調(diào)用微信支付獲取支付參數(shù)返回到前端。這樣用戶看到的就是直接拉起支付。

2.當(dāng)你執(zhí)行支付操作后你的支付回調(diào)接口會(huì)收到支付結(jié)果,這個(gè)時(shí)候你服務(wù)端要主動(dòng)通知小程序,并且當(dāng)小程序拉起支付后要定時(shí)調(diào)用支付查詢接口來主動(dòng)查詢支付完成支付。做個(gè)雙保險(xiǎn)比較好。

3.微信支付完成后有個(gè)"完成"按鈕,點(diǎn)擊后就會(huì)回到wx.requestPayment的success回調(diào)里,這里最好也要查詢下訂單狀態(tài)。

4.還有點(diǎn)我還沒怎么做處理,也是個(gè)題外話,就是當(dāng)支付回調(diào)時(shí)服務(wù)器掛了咋整,得想個(gè)萬全之策,這個(gè)就交給你們解答了。

到此這篇關(guān)于利用微信小程序+JAVA實(shí)現(xiàn)微信支付的文章就介紹到這了,更多相關(guān)微信小程序 JAVA實(shí)現(xiàn)微信支付內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計(jì)模式的策略模式簡(jiǎn)析

    Java設(shè)計(jì)模式的策略模式簡(jiǎn)析

    這篇文章主要介紹了Java設(shè)計(jì)模式的策略模式簡(jiǎn)析,策略模式中定義了一系列的算法族,算法族指的是類似于一系列的行為、策略,策略模式將一系列的行為封裝成類,既可以說是將每一種相類似的行為都封裝成一個(gè)類,也有可能存在特殊的不進(jìn)行封裝的行為,需要的朋友可以參考下
    2023-12-12
  • java使用多線程讀取超大文件

    java使用多線程讀取超大文件

    這篇文章主要為大家詳細(xì)介紹了java使用多線程讀取超大文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • SpringBoot高級(jí)配置之臨時(shí)屬性、配置文件、日志、多環(huán)境配置詳解

    SpringBoot高級(jí)配置之臨時(shí)屬性、配置文件、日志、多環(huán)境配置詳解

    這篇文章主要介紹了SpringBoot高級(jí)配置之臨時(shí)屬性、配置文件、日志、多環(huán)境配置,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • 使用spring stream發(fā)送消息代碼實(shí)例

    使用spring stream發(fā)送消息代碼實(shí)例

    這篇文章主要介紹了使用spring stream發(fā)送消息代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • java實(shí)戰(zhàn)技巧之if-else代碼優(yōu)化技巧大全

    java實(shí)戰(zhàn)技巧之if-else代碼優(yōu)化技巧大全

    代碼中如果if-else比較多,閱讀起來比較困難,維護(hù)起來也比較困難,很容易出bug,下面這篇文章主要給大家介紹了關(guān)于java實(shí)戰(zhàn)技巧之if-else代碼優(yōu)化技巧的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • 使用HttpClient調(diào)用接口的實(shí)例講解

    使用HttpClient調(diào)用接口的實(shí)例講解

    下面小編就為大家?guī)硪黄褂肏ttpClient調(diào)用接口的實(shí)例講解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • idea雙擊圖標(biāo)打不開,無反應(yīng)的解決

    idea雙擊圖標(biāo)打不開,無反應(yīng)的解決

    這篇文章主要介紹了idea雙擊圖標(biāo)打不開,無反應(yīng)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Java中bcrypt算法實(shí)現(xiàn)密碼加密的方法步驟

    Java中bcrypt算法實(shí)現(xiàn)密碼加密的方法步驟

    我們可以在Spring Boot和SSM中實(shí)現(xiàn)密碼加密,使用bcrypt算法可以保障密碼的安全性,并且減少了手動(dòng)編寫哈希函數(shù)的工作量,本文就來詳細(xì)的介紹一下,感興趣的可以了解一下
    2023-08-08
  • Spring框架初始化解析

    Spring框架初始化解析

    這篇文章主要介紹了Spring框架初始化解析,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Java中關(guān)于isEmpty方法、null以及““的區(qū)別

    Java中關(guān)于isEmpty方法、null以及““的區(qū)別

    這篇文章主要介紹了Java中關(guān)于isEmpty方法、null以及““的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評(píng)論