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

SpringBoot集成支付寶支付的實(shí)現(xiàn)示例

 更新時(shí)間:2023年06月15日 09:00:34   作者:碼老思  
本文主要介紹了SpringBoot集成支付寶支付的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

最近在做一個(gè)網(wǎng)站,后端采用了SpringBoot,需要集成支付寶進(jìn)行線上支付,在這個(gè)過程中研究了大量支付寶的集成資料,也走了一些彎路,現(xiàn)在總結(jié)出來,相信你讀完也能輕松集成支付寶支付。

在開始集成支付寶支付之前,我們需要準(zhǔn)備一個(gè)支付寶商家賬戶,如果是個(gè)人開發(fā)者,可以通過注冊公司或者讓有公司資質(zhì)的單位進(jìn)行授權(quán),后續(xù)在集成相關(guān)API的時(shí)候需要提供這些信息。

下面我以電腦網(wǎng)頁端在線支付為例,介紹整個(gè)從集成、測試到上線的具體流程。

1. 預(yù)期效果展示

在開始之前我們先看下我們要達(dá)到的最后效果,具體如下:

  • 前端點(diǎn)擊支付跳轉(zhuǎn)到支付寶界面
  • 支付寶界面展示付款二維碼
  • 用戶手機(jī)端支付
  • 完成支付,支付寶回調(diào)開發(fā)者指定的url。

TYkvEC

2. 開發(fā)流程

2.1 沙盒調(diào)試

支付寶為我們準(zhǔn)備了完善的沙盒開發(fā)環(huán)境,我們可以先在沙盒環(huán)境調(diào)試好程序,后續(xù)新建好應(yīng)用并成功上線后,把程序中對(duì)應(yīng)的參數(shù)替換為線上參數(shù)即可。

1. 創(chuàng)建沙盒應(yīng)用

直接進(jìn)入 open.alipay.com/develop/san… 創(chuàng)建沙盒應(yīng)用即可,

gkD18n

這里因?yàn)槭菧y試環(huán)境,我們就選擇系統(tǒng)默認(rèn)密鑰就行了,下面選擇公鑰模式,另外應(yīng)用網(wǎng)關(guān)地址就是用戶完成支付之后,支付寶會(huì)回調(diào)的url。在開發(fā)環(huán)境中,我們可以采用內(nèi)網(wǎng)穿透的方式,將我們本機(jī)的端口暴露在某個(gè)公網(wǎng)地址上,這里推薦 natapp.cn/ ,可以免費(fèi)注冊使用。

2. SpringBoot代碼實(shí)現(xiàn)

在創(chuàng)建好沙盒應(yīng)用,獲取到密鑰,APPID,商家賬戶PID等信息之后,就可以在測試環(huán)境開發(fā)集成對(duì)應(yīng)的API了。這里我以電腦端支付API為例,介紹如何進(jìn)行集成。

關(guān)于電腦網(wǎng)站支付的詳細(xì)產(chǎn)品介紹和API接入文檔可以參考:opendocs.alipay.com/open/repo-0038oa?ref=apiopendocs.alipay.com/open/270/01didh?ref=api

步驟1, 添加alipay sdk對(duì)應(yīng)的Maven依賴。

<!-- alipay -->  <dependency>     <groupId>com.alipay.sdk</groupId>     <artifactId>alipay-sdk-java</artifactId>     <version>4.35.132.ALL</version>  </dependency>

步驟2,添加支付寶下單、支付成功后同步調(diào)用和異步調(diào)用的接口。

這里需要注意,同步接口是用戶完成支付后會(huì)自動(dòng)跳轉(zhuǎn)的地址,因此需要是Get請求。異步接口,是用戶完成支付之后,支付寶會(huì)回調(diào)來通知支付結(jié)果的地址,所以是POST請求。

@RestController  
@RequestMapping("/alipay")  
public class AliPayController {  
    @Autowired  
    AliPayService aliPayService;  
    @PostMapping("/order")  
    public GenericResponse<Object> placeOrderForPCWeb(@RequestBody AliPayRequest aliPayRequest) {  
        try {  
            return aliPayService.placeOrderForPCWeb(aliPayRequest);  
        } catch (IOException e) {  
            throw new RuntimeException(e);  
        }  
    }  
    @PostMapping("/callback/async")  
    public String asyncCallback(HttpServletRequest request) {  
        return aliPayService.orderCallbackInAsync(request);  
    }  
    @GetMapping("/callback/sync")  
    public void syncCallback(HttpServletRequest request, HttpServletResponse response) {  
        aliPayService.orderCallbackInSync(request, response);  
    }  
}

步驟3,實(shí)現(xiàn)Service層代碼

這里針對(duì)上面controller中的三個(gè)接口,分別完成service層對(duì)應(yīng)的方法。下面是整個(gè)支付的核心流程,其中有些地方需要根據(jù)你自己的實(shí)際情況進(jìn)行保存訂單到DB或者檢查訂單狀態(tài)的操作,這個(gè)可以根據(jù)實(shí)際業(yè)務(wù)需求進(jìn)行設(shè)計(jì)。

public class AliPayService {  
    @Autowired  
    AliPayHelper aliPayHelper;  
    @Resource  
    AlipayConfig alipayConfig;  
    @Transactional(rollbackFor = Exception.class)  
    public GenericResponse<Object> placeOrderForPCWeb(AliPayRequest aliPayRequest) throws IOException {  
        log.info("【請求開始-在線購買-交易創(chuàng)建】*********統(tǒng)一下單開始*********");  
        String tradeNo = aliPayHelper.generateTradeNumber();  
        String subject = "購買套餐1";  
        Map<String, Object> map = aliPayHelper.placeOrderAndPayForPCWeb(tradeNo, 100, subject);  
        if (Boolean.parseBoolean(String.valueOf(map.get("isSuccess")))) {  
            log.info("【請求開始-在線購買-交易創(chuàng)建】統(tǒng)一下單成功,開始保存訂單數(shù)據(jù)");  
            //保存訂單信息  
            // 添加你自己的業(yè)務(wù)邏輯,主要是保存訂單數(shù)據(jù)
            log.info("【請求成功-在線購買-交易創(chuàng)建】*********統(tǒng)一下單結(jié)束*********");  
            return new GenericResponse<>(ResponseCode.SUCCESS, map.get("body"));  
        }else{  
            log.info("【失敗:請求失敗-在線購買-交易創(chuàng)建】*********統(tǒng)一下單結(jié)束*********");  
            return new GenericResponse<>(ResponseCode.INTERNAL_ERROR, String.valueOf(map.get("subMsg")));  
        }  
    }  
    // sync return page  
    public void orderCallbackInSync(HttpServletRequest request, HttpServletResponse response) {  
        try {  
            OutputStream outputStream = response.getOutputStream();  
            //通過設(shè)置響應(yīng)頭控制瀏覽器以UTF-8的編碼顯示數(shù)據(jù),如果不加這句話,那么瀏覽器顯示的將是亂碼  
            response.setHeader("content-type", "text/html;charset=UTF-8");  
            String outputData = "支付成功,請返回網(wǎng)站并刷新頁面。";  
            /**  
             * data.getBytes()是一個(gè)將字符轉(zhuǎn)換成字節(jié)數(shù)組的過程,這個(gè)過程中一定會(huì)去查碼表,  
             * 如果是中文的操作系統(tǒng)環(huán)境,默認(rèn)就是查找查GB2312的碼表,  
             */  
            byte[] dataByteArr = outputData.getBytes("UTF-8");//將字符轉(zhuǎn)換成字節(jié)數(shù)組,指定以UTF-8編碼進(jìn)行轉(zhuǎn)換  
            outputStream.write(dataByteArr);//使用OutputStream流向客戶端輸出字節(jié)數(shù)組  
        } catch (IOException e) {  
            throw new RuntimeException(e);  
        }  
    }  
    public String orderCallbackInAsync(HttpServletRequest request) {  
        try {  
            Map<String, String> map = aliPayHelper.paramstoMap(request);  
            String tradeNo = map.get("out_trade_no");  
            String sign = map.get("sign");  
            String content = AlipaySignature.getSignCheckContentV1(map);  
            boolean signVerified = aliPayHelper.CheckSignIn(sign, content);  
            // check order status  
            // 這里在DB中檢查order的狀態(tài),如果已經(jīng)支付成功,無需再次驗(yàn)證。
            if(從DB中拿到order,并且判斷order是否支付成功過){  
                log.info("訂單:" + tradeNo + " 已經(jīng)支付成功,無需再次驗(yàn)證。");  
                return "success";  
            }  
            //驗(yàn)證業(yè)務(wù)數(shù)據(jù)是否一致  
            if(!checkData(map, order)){  
                log.error("返回業(yè)務(wù)數(shù)據(jù)驗(yàn)證失敗,訂單:" + tradeNo );  
                return "返回業(yè)務(wù)數(shù)據(jù)驗(yàn)證失敗";  
            }  
            //簽名驗(yàn)證成功  
            if(signVerified){  
                log.info("支付寶簽名驗(yàn)證成功,訂單:" + tradeNo);  
                // 驗(yàn)證支付狀態(tài)  
                String tradeStatus = request.getParameter("trade_status");  
                if(tradeStatus.equals("TRADE_SUCCESS")){  
                    log.info("支付成功,訂單:"+tradeNo);  
			        // 更新訂單狀態(tài),執(zhí)行一些業(yè)務(wù)邏輯
                    return "success";  
                }else{  
                    System.out.println("支付失敗,訂單:" + tradeNo );  
                    return "支付失敗";  
                }  
            }else{  
                log.error("簽名驗(yàn)證失敗,訂單:" + tradeNo );  
                return "簽名驗(yàn)證失敗.";  
            }  
        } catch (IOException e) {  
            log.error("IO exception happened ", e);  
            throw new RuntimeException(ResponseCode.INTERNAL_ERROR, e.getMessage());  
        }  
    }  
    public boolean checkData(Map<String, String> map, OrderInfo order) {  
        log.info("【請求開始-交易回調(diào)-訂單確認(rèn)】*********校驗(yàn)訂單確認(rèn)開始*********");  
        //驗(yàn)證訂單號(hào)是否準(zhǔn)確,并且訂單狀態(tài)為待支付  
        if(驗(yàn)證訂單號(hào)是否準(zhǔn)確,并且訂單狀態(tài)為待支付){  
            float amount1 = Float.parseFloat(map.get("total_amount"));  
            float amount2 = (float) order.getOrderAmount();  
            //判斷金額是否相等  
            if(amount1 == amount2){  
                //驗(yàn)證收款商戶id是否一致  
                if(map.get("seller_id").equals(alipayConfig.getPid())){  
                    //判斷appid是否一致  
                    if(map.get("app_id").equals(alipayConfig.getAppid())){  
                        log.info("【成功:請求開始-交易回調(diào)-訂單確認(rèn)】*********校驗(yàn)訂單確認(rèn)成功*********");  
                        return true;                    }  
                }  
            }  
        }  
        log.info("【失?。赫埱箝_始-交易回調(diào)-訂單確認(rèn)】*********校驗(yàn)訂單確認(rèn)失敗*********");  
        return false;    }  
}

步驟4,實(shí)現(xiàn)alipayHelper類。這個(gè)類里面對(duì)支付寶的接口進(jìn)行封裝。

public class AliPayHelper {  
    @Resource  
    private AlipayConfig alipayConfig;  
    //返回?cái)?shù)據(jù)格式  
    private static final String FORMAT = "json";  
    //編碼類型  
    private static final String CHART_TYPE = "utf-8";  
    //簽名類型  
    private static final String SIGN_TYPE = "RSA2";  
    /*支付銷售產(chǎn)品碼,目前支付寶只支持FAST_INSTANT_TRADE_PAY*/  
    public static final String PRODUCT_CODE = "FAST_INSTANT_TRADE_PAY";  
    private static AlipayClient alipayClient = null;  
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");  
    private static final Random random = new Random();  
    @PostConstruct  
    public void init(){  
        alipayClient = new DefaultAlipayClient(  
                alipayConfig.getGateway(),  
                alipayConfig.getAppid(),  
                alipayConfig.getPrivateKey(),  
                FORMAT,  
                CHART_TYPE,  
                alipayConfig.getPublicKey(),  
                SIGN_TYPE);  
    };  
    /*================PC網(wǎng)頁支付====================*/  
    /**  
     * 統(tǒng)一下單并調(diào)用支付頁面接口  
     * @param outTradeNo  
     * @param totalAmount  
     * @param subject  
     * @return  
     */  
    public Map<String, Object> placeOrderAndPayForPCWeb(String outTradeNo, float totalAmount, String subject){  
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();  
        request.setNotifyUrl(alipayConfig.getNotifyUrl());  
        request.setReturnUrl(alipayConfig.getReturnUrl());  
        JSONObject bizContent = new JSONObject();  
        bizContent.put("out_trade_no", outTradeNo);  
        bizContent.put("total_amount", totalAmount);  
        bizContent.put("subject", subject);  
        bizContent.put("product_code", PRODUCT_CODE);  
        request.setBizContent(bizContent.toString());  
        AlipayTradePagePayResponse response = null;  
        try {  
            response = alipayClient.pageExecute(request);  
        } catch (AlipayApiException e) {  
            e.printStackTrace();  
        }  
        Map<String, Object> resultMap = new HashMap<>();  
        resultMap.put("isSuccess", response.isSuccess());  
        if(response.isSuccess()){  
            log.info("調(diào)用成功");  
            log.info(JSON.toJSONString(response));  
            resultMap.put("body", response.getBody());  
        } else {  
            log.error("調(diào)用失敗");  
            log.error(response.getSubMsg());  
            resultMap.put("subMsg", response.getSubMsg());  
        }  
        return resultMap;  
    }  
    /**  
     * 交易訂單查詢  
     * @param out_trade_no  
     * @return  
     */  
    public Map<String, Object> tradeQueryForPCWeb(String out_trade_no){  
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();  
        JSONObject bizContent = new JSONObject();  
        bizContent.put("trade_no", out_trade_no);  
        request.setBizContent(bizContent.toString());  
        AlipayTradeQueryResponse response = null;  
        try {  
            response = alipayClient.execute(request);  
        } catch (AlipayApiException e) {  
            e.printStackTrace();  
        }  
        Map<String, Object> resultMap = new HashMap<>();  
        resultMap.put("isSuccess", response.isSuccess());  
        if(response.isSuccess()){  
            System.out.println("調(diào)用成功");  
            System.out.println(JSON.toJSONString(response));  
            resultMap.put("status", response.getTradeStatus());  
        } else {  
            System.out.println("調(diào)用失敗");  
            System.out.println(response.getSubMsg());  
            resultMap.put("subMsg", response.getSubMsg());  
        }  
        return resultMap;  
    }  
    /**  
     * 驗(yàn)證簽名是否正確  
     * @param sign  
     * @param content  
     * @return  
     */  
    public boolean CheckSignIn(String sign, String content){  
        try {  
            return AlipaySignature.rsaCheck(content, sign, alipayConfig.getPublicKey(), CHART_TYPE, SIGN_TYPE);  
        } catch (AlipayApiException e) {  
            e.printStackTrace();  
        }  
        return false;  
    }  
    /**  
     * 將異步通知的參數(shù)轉(zhuǎn)化為Map  
     * @return  
     */  
    public Map<String, String> paramstoMap(HttpServletRequest request) throws UnsupportedEncodingException {  
        Map<String, String> params = new HashMap<String, String>();  
        Map<String, String[]> requestParams = request.getParameterMap();  
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {  
            String name = (String) iter.next();  
            String[] values = (String[]) requestParams.get(name);  
            String valueStr = "";  
            for (int i = 0; i < values.length; i++) {  
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";  
            }  
            // 亂碼解決,這段代碼在出現(xiàn)亂碼時(shí)使用。  
//            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");  
            params.put(name, valueStr);  
        }  
        return params;  
    }  
}

步驟5,封裝config類,用于存放所有的配置屬性。

@Data  
@Component  
@ConfigurationProperties(prefix = "alipay")  
public class AlipayConfig {  
    private String gateway;  
    private String appid;  
    private String pid;  
    private String privateKey;  
    private String publicKey;  
    private String returnUrl;  
    private String notifyUrl;  
}

另外需要在application.properties中,準(zhǔn)備好上述對(duì)應(yīng)的屬性。

# alipay config  
alipay.gateway=https://openapi.alipaydev.com/gateway.do  
alipay.appid=your_appid
alipay.pid=your_pid  
alipay.privatekey=your_private_key
alipay.publickey=your_public_key
alipay.returnurl=完成支付后的同步跳轉(zhuǎn)地址 
alipay.notifyurl=完成支付后,支付寶會(huì)異步回調(diào)的地址

3. 前端代碼實(shí)現(xiàn)

前端代碼只需要完成兩個(gè)功能,

  • 根據(jù)用戶的請求向后端發(fā)起支付請求。
  • 直接提交返回?cái)?shù)據(jù)完成跳轉(zhuǎn)。

下面的例子中,我用typescript實(shí)現(xiàn)了用戶點(diǎn)擊支付之后的功能,

async function onPositiveClick() {  
   paymentLoading.value = true  
   const { data } = await placeAlipayOrder<string>({  
	//你的一些請求參數(shù),例如金額等等
   })  
   const div = document.createElement('divform')  
   div.innerHTML = data  
   document.body.appendChild(div)  
   document.forms[0].setAttribute('target', '_blank')  
   document.forms[0].submit()  
   showModal.value = false  
   paymentLoading.value = false  
}

2.2 創(chuàng)建并上線APP

完成沙盒調(diào)試沒問題之后,我們需要?jiǎng)?chuàng)建對(duì)應(yīng)的支付寶網(wǎng)頁應(yīng)用并上線。

登錄 open.alipay.com/develop/man… 并選擇創(chuàng)建網(wǎng)頁應(yīng)用,

Ft3uVP

填寫應(yīng)用相關(guān)信息:

rawj0Q

創(chuàng)建好應(yīng)用之后,首先在開發(fā)設(shè)置中,設(shè)置好接口加簽方式以及應(yīng)用網(wǎng)關(guān)。

NEhv2p

注意密鑰選擇RSA2,其他按照上面的操作指南一步步走即可,注意保管好自己的私鑰和公鑰。

之后在產(chǎn)品綁定頁,綁定對(duì)應(yīng)的API,比如我們這里是PC網(wǎng)頁端支付,找到對(duì)應(yīng)的API綁定就可以了。如果第一次綁定,可能需要填寫相關(guān)的信息進(jìn)行審核,按需填寫即可,一般審核一天就通過了。

6V0i4b

最后如果一切就緒,我們就可以把APP提交上線了,上線成功之后,我們需要把下面SpringBoot中的properties替換為線上APP的信息,然后就可以在生產(chǎn)環(huán)境調(diào)用支付寶的接口進(jìn)行支付了。

# alipay config  
alipay.gateway=https://openapi.alipaydev.com/gateway.do  
alipay.appid=your_appid
alipay.pid=your_pid  
alipay.privatekey=your_private_key
alipay.publickey=your_public_key
alipay.returnurl=完成支付后的同步跳轉(zhuǎn)地址 
alipay.notifyurl=完成支付后,支付寶會(huì)異步回調(diào)的地址

參考:

https://blog.csdn.net/xqnode/article/details/124457790

https://blog.51cto.com/u_15754099/5585676

https://zhuanlan.zhihu.com/p/596771147

https://segmentfault.com/a/1190000041974184

到此這篇關(guān)于SpringBoot集成支付寶支付的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot支付寶支付內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java方法的返回值及注意事項(xiàng)小結(jié)

    Java方法的返回值及注意事項(xiàng)小結(jié)

    這篇文章主要介紹了Java方法的返回值及注意事項(xiàng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • java 枚舉類定義靜態(tài)valueOf(java.lang.String)方法的問題及解決

    java 枚舉類定義靜態(tài)valueOf(java.lang.String)方法的問題及解決

    這篇文章主要介紹了java 枚舉類定義靜態(tài)valueOf(java.lang.String)方法的問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java Jackson之ObjectMapper常用用法總結(jié)

    Java Jackson之ObjectMapper常用用法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java Jackson之ObjectMapper常用用法的相關(guān)資料,ObjectMapper是一個(gè)Java庫,用于將JSON字符串轉(zhuǎn)換為Java對(duì)象或?qū)ava對(duì)象轉(zhuǎn)換為JSON字符串,需要的朋友可以參考下
    2024-01-01
  • Spring使用@Value注解與@PropertySource注解加載配置文件操作

    Spring使用@Value注解與@PropertySource注解加載配置文件操作

    這篇文章主要介紹了Spring使用@Value注解與@PropertySource注解加載配置文件操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Spring中的@PathVariable注解詳細(xì)解析

    Spring中的@PathVariable注解詳細(xì)解析

    這篇文章主要介紹了Spring中的@PathVariable注解詳細(xì)解析,@PathVariable 是 Spring 框架中的一個(gè)注解,用于將 URL 中的變量綁定到方法的參數(shù)上,它通常用于處理 RESTful 風(fēng)格的請求,從 URL 中提取參數(shù)值,并將其傳遞給方法進(jìn)行處理,需要的朋友可以參考下
    2024-01-01
  • java逐行讀取文件(讀取文件每一行、按行讀取文件)附帶詳細(xì)代碼

    java逐行讀取文件(讀取文件每一行、按行讀取文件)附帶詳細(xì)代碼

    這篇文章主要給大家介紹了關(guān)于java逐行讀取文件(讀取文件每一行、按行讀取文件)的相關(guān)資料,讀取文件是我們在日常工作中經(jīng)常遇到的一個(gè)需求,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • mybatis批量添加,批量更新之前如何判斷是否已經(jīng)存在

    mybatis批量添加,批量更新之前如何判斷是否已經(jīng)存在

    這篇文章主要介紹了mybatis批量添加,批量更新之前如何判斷是否已經(jīng)存在,具有很好的參考價(jià)值,希望對(duì)的有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 簡單了解java自定義和自然排序

    簡單了解java自定義和自然排序

    這篇文章主要介紹了簡單了解java自定義和自然排序,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 深入分析java并發(fā)編程中volatile的實(shí)現(xiàn)原理

    深入分析java并發(fā)編程中volatile的實(shí)現(xiàn)原理

    這篇文章主要介紹了深入分析java并發(fā)編程中Volatile的實(shí)現(xiàn)原理,涉及Volatile的官方定義,實(shí)現(xiàn)原理,使用優(yōu)化等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • java gui詳解貪吃蛇小游戲?qū)崿F(xiàn)流程

    java gui詳解貪吃蛇小游戲?qū)崿F(xiàn)流程

    剛開始學(xué)JAVA GUI,就練手寫了一個(gè)小時(shí)候經(jīng)常在諾基亞上玩的一個(gè)小游戲__貪吃蛇.做的比較簡單,但還是可以玩的.感興趣的朋友快來看看吧
    2021-11-11

最新評(píng)論