diff --git a/dl_admin/ruoyi-admin/pom.xml b/dl_admin/ruoyi-admin/pom.xml index 132c9de..8666b85 100644 --- a/dl_admin/ruoyi-admin/pom.xml +++ b/dl_admin/ruoyi-admin/pom.xml @@ -148,7 +148,7 @@ com.google.api-ads google-ads - 28.0.0 + 38.0.0 diff --git a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/base/controller/WebController.java b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/base/controller/WebController.java index 93a7b84..7d35590 100644 --- a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/base/controller/WebController.java +++ b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/base/controller/WebController.java @@ -14,10 +14,7 @@ import com.ruoyi.busi.domain.BusiCategory; import com.ruoyi.busi.domain.BusiChatMain; import com.ruoyi.busi.domain.BusiInquiryItem; import com.ruoyi.busi.domain.BusiProdNew; -import com.ruoyi.busi.service.IBusiCategoryService; -import com.ruoyi.busi.service.IBusiChatMainService; -import com.ruoyi.busi.service.IBusiInquiryItemService; -import com.ruoyi.busi.service.IBusiProdNewService; +import com.ruoyi.busi.service.*; import com.ruoyi.busi.utils.CommonUtils; import com.ruoyi.busi.vo.BusiCategoryVO; import com.ruoyi.busi.vo.ProdNewVO; @@ -72,6 +69,8 @@ public class WebController extends BaseController { private IBusiInquiryItemService inquiryItemService; @Autowired private IBusiChatMainService busiChatMainService; + @Autowired + private GoogleKeywordService googleKeywordService; /** * 导航栏接口--所有分类 @@ -412,4 +411,10 @@ public class WebController extends BaseController { inquiryItemService.save(inquiryItem); return R.ok(); } + + @GetMapping("/test") + public R test(){ + googleKeywordService.test(); + return R.ok(); + } } diff --git a/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/busi/service/GoogleKeywordService.java b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/busi/service/GoogleKeywordService.java new file mode 100644 index 0000000..e72e5fd --- /dev/null +++ b/dl_admin/ruoyi-admin/src/main/java/com/ruoyi/busi/service/GoogleKeywordService.java @@ -0,0 +1,128 @@ +package com.ruoyi.busi.service; + +import com.google.ads.googleads.lib.GoogleAdsClient; +import com.google.ads.googleads.v20.common.Keyword; +import com.google.ads.googleads.v20.common.KeywordAnnotations; +import com.google.ads.googleads.v20.common.KeywordConcept; +import com.google.ads.googleads.v20.enums.KeywordPlanKeywordAnnotationEnum; +import com.google.ads.googleads.v20.enums.KeywordPlanNetworkEnum; +import com.google.ads.googleads.v20.enums.KeywordPlanKeywordAnnotationEnum.KeywordPlanKeywordAnnotation; +import com.google.ads.googleads.v20.services.*; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.ruoyi.common.config.GoogleConfig; +import com.ruoyi.common.config.OssConfig; +import lombok.var; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ResourceUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +@Service +public class GoogleKeywordService { + @Autowired + private GoogleConfig googleConfig; + + public void test() { + try { + // 1. 检查文件是否存在 + File file = ResourceUtils.getFile("file:" + googleConfig.getJsonPath()); + boolean fileExists = file.exists(); + System.out.println("JSON 文件是否存在: " + fileExists); + + // 2. 加载 JSON 凭证 + GoogleCredentials credentials = ServiceAccountCredentials.fromStream( + new FileInputStream(file) + ); + // 2. 构建 GoogleAdsClient(自动读取环境变量) + GoogleAdsClient googleAdsClient = GoogleAdsClient.newBuilder() + .setCredentials(credentials) + .setDeveloperToken(googleConfig.getDeveloperToken()) + .setLoginCustomerId(googleConfig.getCustomerId()) + .build(); + + // 2. 设置参数 + List seedKeywords = Arrays.asList("TRUCK"); + // 英语 + String language = "languageConstants/1000"; + // 美国 + String geoTarget = "geoTargetConstants/2840"; + + // 3. 获取关键词提示 + List keywordIdeas = generateKeywordIdeas( + googleAdsClient, googleConfig.getCustomerId(), seedKeywords, language, geoTarget); + + // 4. 输出结果 + for (GenerateKeywordIdeaResult idea : keywordIdeas) { + // 获取关键词文本 + String text = idea.getText(); + // 获取关键词指标(可选) + if (idea.hasKeywordIdeaMetrics()) { + long avgMonthlySearches = idea.getKeywordIdeaMetrics().getAvgMonthlySearches(); + String competition = String.valueOf(idea.getKeywordIdeaMetrics().getCompetition()); + System.out.println("找到的关键词文本:" + text+";月搜索量:" + avgMonthlySearches+";竞争程度:" + competition); + } + } + } catch (IOException e) { + System.err.printf("初始化 Google Ads 客户端失败: %s%n", e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 生成关键词提示 + * + * @param googleAdsClient Google Ads 客户端 + * @param customerId 客户ID + * @param seedKeywords 种子关键词列表 + * @param language 语言常量 (如 "languageConstants/1000" 表示英语) + * @param geoTarget 地理位置目标常量 (如 "geoTargetConstants/2840" 表示美国) + * @return 关键词提示列表 + * @throws IOException 如果API调用失败 + */ + public static List generateKeywordIdeas( + GoogleAdsClient googleAdsClient, + long customerId, + List seedKeywords, + String language, + String geoTarget) throws IOException { + + List allKeywordIdeas = new ArrayList<>(); + String nextPageToken = null; + + KeywordAndUrlSeed seed = KeywordAndUrlSeed.newBuilder() + .addAllKeywords(seedKeywords) + .setUrl("https://www.cdtruck.com/truck/dump-truck/china-sinotruk-howo-19m3-6x4-cheap-336hp-10.html") // 提供相关 URL + .build(); + do { + try (KeywordPlanIdeaServiceClient client = + googleAdsClient.getLatestVersion().createKeywordPlanIdeaServiceClient()) { + GenerateKeywordIdeasRequest.Builder requestBuilder = GenerateKeywordIdeasRequest.newBuilder() + .setCustomerId(Long.toString(customerId)) + .setLanguage(language) + .addAllGeoTargetConstants(Collections.singletonList(geoTarget)) + .setKeywordPlanNetwork(KeywordPlanNetworkEnum.KeywordPlanNetwork.GOOGLE_SEARCH_AND_PARTNERS) + .setKeywordAndUrlSeed(seed); + // 仅在非首次请求时设置 pageToken + if (nextPageToken != null) { + requestBuilder.setPageToken(nextPageToken); + } + GenerateKeywordIdeasRequest request = requestBuilder.build(); + GenerateKeywordIdeaResponse response = client.generateKeywordIdeasCallable().call(request); + allKeywordIdeas.addAll(response.getResultsList()); + nextPageToken = response.getNextPageToken(); + System.out.println("分页token:"+nextPageToken); + } + } while (StringUtils.isNotEmpty(nextPageToken)); + System.out.println("关键词总数:"+allKeywordIdeas.size()); + return allKeywordIdeas; + } + +} \ No newline at end of file diff --git a/dl_admin/ruoyi-admin/src/main/resources/application.yml b/dl_admin/ruoyi-admin/src/main/resources/application.yml index 5d98a27..72bbbb2 100644 --- a/dl_admin/ruoyi-admin/src/main/resources/application.yml +++ b/dl_admin/ruoyi-admin/src/main/resources/application.yml @@ -150,5 +150,10 @@ aliyun: access-key-id: LTAI5tLThQFWgMLRTf3siNjb access-key-secret: M5HjOyB8ir5tYEPFOQwImfJNgsumaG bucket-name: dianliang123 - +#google ads配置 +google: + ads: + customer-id: 4577179829 + developer-token: qwFA3dGfOGqEhSEHlCMorA + json-path: /www/wwwroot/nuxt/test.json diff --git a/dl_admin/ruoyi-admin/src/main/resources/chengda.json b/dl_admin/ruoyi-admin/src/main/resources/chengda.json new file mode 100644 index 0000000..d8ab738 --- /dev/null +++ b/dl_admin/ruoyi-admin/src/main/resources/chengda.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "chengda-466307", + "private_key_id": "c4f38952fb0922ff625a85d364543f415f93d03d", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCRIuvHsOaOnXv5\nlLl3R0fLrWjd8fk6tDv1bIJFpC2xfFem2rYaG1IFJVfnGgCAL7P4j6tVn0j684dL\n2wb4BRJjyK4EDYBLkugc3BWNnpt6z80f8+U39/QtDwRBJqQGvRD4LGhm5dDrAWhf\ngeiCKVC+3TGDGDwkt4JjuZQ6/GSrvX9aSaLyT5PlpYSvxH2tetb5rY6LdeAR9wS1\n0dtFD0jIxYHm96vWpe1LLhtw+28thxYeR7VFOZf6HzJLDDOt4hYbHoo+DAKaPIyC\n6+CepAcE13WWn7ooPGjh8JAGPqs2JpqR6ujFrvYXAto3UvpXSV0W6h1gRv9AD3SW\n33Te4KYzAgMBAAECggEAEu74zkCsGx+9TBZUSZSxb4csPoPyDO/1QHOK3RXpZhWA\nA8LVbbtxrD0uZfYU6aQPeNYZNl7EsQQy+rjUhGd4+i50URAH1BQSlq05XJO72b4h\nFtGE7hO5NWWXmv40+LISdCWq6v2BDx9MY+U5FT3ZjESj0GPJeMq9xk+v4DAL3AF2\nqsXsL/GhSLTyIWufIaxwUPFfumVVqjH3r9B1YqY+0Z//E/2I9W3NOSQ83JzI1osw\nQ5ybQdQ9zQptlr/kh9sb+vtgJ4+7h6RQ6Xcyy6OsW4Kg6Ho7eRTBDIytv9o7Ef+h\nVYwV6OjonAcWcbfCY2TGEO2DDJJbkZZwRby2WE5jkQKBgQDMQt/XfWCI2EVPNwpn\nl6gFY7vWcXSO+dkEloFgIpbxiJTmZTRmWPnpqqEaxUNo2KCxyuUoOCC7B+D6AdRI\nBZfxaFtQe+f71oocnWbjNtzLvW8cnZouHI1pT+HXWO84aq7fh4lkYhXsEZkhu2Ce\nV1nGjSVboe/OJ+Z9oCNVQxtlsQKBgQC15idlkFZbCR3zBDmc9LRDC1iZXyhBlSva\nT30e1M7sOO8lN2Uw825XaP4CKE70jOxL5eLkSvXALWOdeVZ79iclAoz+iE8FsLPf\nbUOWAEuUtsgyyrmkcKU/ddvtvEwsBFqZ0CxxqOCDXj+uXoGifyFLigkl3w5wvY0s\njpe1wipvIwKBgQCUvvpc5XugC8ZlSlK0X5dG3XsTTamw2Lc2BRgP1wCOwYSVRwvi\noFbV16DcatyNBHv5HSTFpiIHsVQfG6foDtK4ROOCd8jW90O6VNFxEym04K2CbC6z\n96zvDPIMrUH/lojkVMIzrM4EDEi0bMyOYlQJKA4VbZbBTQMnZq90Tpsr8QKBgQCr\nd/k9aZGuIWsFEb+JsLdY2BI+ChC1ufvrwLDO5obk8UqmR5DxUxh597QyrnK3XzzE\n00FOOUduUJst8BrRohoGbmAg9LehQpBdFu/2L/MPjjosfyP+2l079EtM0QrxF22c\nvzuWLT7vN2JKajZDyxnEzquO8rT3HAg/r29d3FoKBwKBgQCM4BNOTBT10gCPKQBx\nApULMInlweLr393rc17cJHSSLmL0z26oIfpJYVf+AbV4sLKE9HaCmwxTiR/frt9f\nEhAaOsWfprl/CFC3kcF/Vndey2v9Nlwdzl7//8c0O8ITlqt+OpK3giOUquMWuG8i\nFU9AwpseRhEp5uHZ5e1wKgsEsA==\n-----END PRIVATE KEY-----\n", + "client_email": "chengdatest@chengda-466307.iam.gserviceaccount.com", + "client_id": "108513526311014104962", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/chengdatest%40chengda-466307.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} diff --git a/dl_admin/ruoyi-admin/src/main/resources/google-ads.properties b/dl_admin/ruoyi-admin/src/main/resources/google-ads.properties index 5b96098..0259589 100644 --- a/dl_admin/ruoyi-admin/src/main/resources/google-ads.properties +++ b/dl_admin/ruoyi-admin/src/main/resources/google-ads.properties @@ -1,6 +1,6 @@ -# Google Ads API ?? -api.googleads.clientId=76632811767-p4ieetlihrr311tfk7hchovo1kcqkh4o.apps.googleusercontent.com -api.googleads.clientSecret=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 -api.googleads.refreshToken=YOUR_REFRESH_TOKEN +# ????????? refreshToken? +api.googleads.pathToCredentialsFile=D:/A_lighting_product/dl_site_system/dl_admin/ruoyi-admin/src/main/resources/chengda.json +# ????? Developer Token api.googleads.developerToken=qwFA3dGfOGqEhSEHlCMorA -api.googleads.loginCustomerId=YOUR_MANAGER_ACCOUNT_ID # ??? MCC ?? +# ????? MCC ?? ID???? MCC) +api.googleads.loginCustomerId=3283220394 \ No newline at end of file diff --git a/dl_admin/ruoyi-admin/src/main/resources/test.json b/dl_admin/ruoyi-admin/src/main/resources/test.json new file mode 100644 index 0000000..9b6b8e9 --- /dev/null +++ b/dl_admin/ruoyi-admin/src/main/resources/test.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "sunny-caldron-467002-e6", + "private_key_id": "a38b797901a6c00d69abfe43374d467fd412871d", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpJv+RAS5dlqbJ\nLruF0ANGpdpobnjTmWLT99x7FvrxDunDCiO5JlqhSa8M+YsnJnluZIN85uAPOzpF\nRWMSmZLtdwz2GH2RdDai6rN88M2O3YiaNYS8AOmXfw5Q2zzchHBCnaXw1EHAENUr\nxD77eeYnlVg5U1gUyFwIeeV/o2YezKdMEA4OIdz7tLz0BdW+7wCH+sGzp7NkStkh\nvcV/sK0TRqVdU5z54cH1ndpinDPPwPyXWpV6r3L1QaeD73kgAOHcc23Rlq5BHbCs\n8CIreUnSN6i3Nix597bd9d0p7yBeEYj0F9UV7F3rkXxo2tA45WlmY+ZlgJMNofAa\n7gKfdvKfAgMBAAECggEAARgmJ3VQldFq9Kxbk0CwxyXbfl+82IU6UnHvJ56Es/gM\n2XnKNuIwL83IUejcDkxxv6wgFf8i0+huMaRT57f0tn3V0ToOhnusA/4UhIJCue8/\nRnLb41nuchcwCEbJ0DW6qT74iVj0zKu1TZqCYhbEaedBlDgYSQBLUHNDiEG60etv\nHX3Vgfjaz0ul1v6SaQVjfixRYzLAIpXFvTCzBynQhdvm1+FhL8u4ABPfTKqxYBet\nz9sGGq7Z6EKOCD+w+ppuZgJlGYgXezZuLSIWZy0I9m/adGcup6xw+mWb2EsYevtG\nthlyumpRtBQVWXIrXshymByOYPy0DNFAcl80+fVcIQKBgQDW090TiMjFhnAKinco\ne8FxwaX43ax2Dl0CZFG/qh7jO8TNrxDADoluMmlQUYgHxn/xoHOmh90XyInSH4pg\nBsOfF7FVmkjnVRQQCHmU3MqbZMcm9EZLS6w29iIpd9eyDgY/KAjksaLP6xTpFc0r\nmWhSShk6SIb8DAvbvJy5iQwt4QKBgQDJkii0gz28nN2n0Bw8VQFwgUw1a88pzWZv\nBY3RaDT9f+c82bMhmNKSsE0hDTnUlpLzo/FGVE1oG6wOS5dMx3YmVKpKGLsKOSP+\nJclzLkYEsJl2Q55gcjD6/4ETtqQ2CFmouBl199iG/aYsvqZafKCCgpmWSKC7/0Cf\nnCVuIBIwfwKBgGDJzYYaj5Jm8p3dKriDoXE2NSf9/9CkwgTs2+QFqqroZ8/fuyU8\np3CNp+M3CJmwNj7P8qsp9VPc1zNjYH3JLmPEUfJmc8g+Da73koeePm5qpkuHrRAJ\nhQqyNEwIoZaoOOpFiFQ5MEiK+r3VQ74L/PNuTRV0TdTLPKCAxv/UnjchAoGAOKnM\npYnrNfVG3iDDfzZKNE00liPbVZ32+KiwCDjqBIULBPERyRUDxNaop+zm39sALltc\nvO9/3w9AW7hmLOA5V2cfg7rWAXa0poIK0kUky7a1PSifAe+30yc2KsuB9+p7AdHW\n3nGwvanaJ+PkMbWtDWMXN8bs4ExN51BmuUFsu5MCgYEAmTq81xDw/tIK6x6QYo1S\nEobTXo7KE01cjraOR0Kjk/MtEKlwBQVcDY79LnLzc2p5H0Jfm6MWIzcg+8pRm+gA\nOROfbhB9omfHWZ0PdNBe5Gd3nzEKQGWvSYcqLhZu+4pXYTbEpJLLfhR83oSldJ26\ng54JAsrVH5nTBbbxxxBXCtA=\n-----END PRIVATE KEY-----\n", + "client_email": "mwjtest@sunny-caldron-467002-e6.iam.gserviceaccount.com", + "client_id": "101980709462554291854", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/mwjtest%40sunny-caldron-467002-e6.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} diff --git a/dl_admin/ruoyi-common/src/main/java/com/ruoyi/common/config/GoogleConfig.java b/dl_admin/ruoyi-common/src/main/java/com/ruoyi/common/config/GoogleConfig.java new file mode 100644 index 0000000..cd88af1 --- /dev/null +++ b/dl_admin/ruoyi-common/src/main/java/com/ruoyi/common/config/GoogleConfig.java @@ -0,0 +1,20 @@ +package com.ruoyi.common.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @description google ads配置类 + * @author vinjor-m + */ +@ConfigurationProperties(prefix = "google.ads") +@Configuration +@Data +public class GoogleConfig { + private Long customerId; + private String developerToken; + private String jsonPath; + + +}