Я работаю с загрузкой Java Spring и пытаюсь завершить интеграцию API подписок PayPal.
У меня есть план подписки на шоу, работающий в WebClient, хотя я не могу завершить функциональность для метода отмены подписки.
Я получаю ошибку 415 --
"message": "415 Unsupported Media Type from POST https://api.sandbox.paypal.com/v1/billing/subscriptions/I-JJ0B8HRKSRYV/cancel",
https://developer.paypal.com/api/rest/responses/
https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_cancel - когда я смотрю на подход curl - он утверждает, что content-type и accept находятся в заголовке - но это также может быть способ, которым я пытался добавить тело?
https://reflectoring.io/spring-webclient/
//метод showSubscriptionDetails
@CrossOrigin
@GetMapping("/api/showsubscriptiondetails")
@ResponseBody
public ResponseEntity<BaseResponse> showSubscriptionDetails(
@RequestParam("subscriptionID") String subscriptionID
) throws PayPalRESTException {
BaseResponse response = new BaseResponse();
String bearerToken = generateAccessToken();
String token = bearerToken.split(" ")[1].trim();
WebClient client = WebClient.create(host);
WebClient.ResponseSpec responseSpec = client.get()
.uri("/v1/billing/subscriptions/"+subscriptionID+"?fields=plan")
.headers(h -> {
h.setBearerAuth(token);
})
.retrieve();
String responseBody = responseSpec.bodyToMono(String.class).block();
ObjectMapper mapper = new ObjectMapper();
JsonNode root = null;
try {
root = mapper.readTree(responseBody);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
JsonNode status = root.path("status");
JsonNode plan = root.path("plan").get("name");
BasicDBObject res = new BasicDBObject();
res.put("status", status);
res.put("plan", plan);
response.setCode("OK");
response.setData(res);
response.setDescription(appMessageLocalUtil.getLanguageMessage("subscription.found"));
return ResponseEntity.ok().body(response);
}
//метод отмены подписки
MultiValueMap<String, String> bodyValues = new LinkedMultiValueMap<>();
bodyValues.add("reason", "too expensive");
String bearerToken = generateAccessToken();
String token = bearerToken.split(" ")[1].trim();
WebClient client = WebClient.create(host);
WebClient.ResponseSpec responseSpec = client.post()
.uri("/v1/billing/subscriptions/"+subscriptionID+"/cancel")
.headers(h -> {
h.setBearerAuth(token);
})
.retrieve();
String responseBody = responseSpec.bodyToMono(String.class).block();
System.out.println("responseSpec-- "+ responseSpec);
System.out.println("responseBody-- "+ responseBody);
... попытки
Я пытался добавить тип контента в заголовок и как часть основной сборки, но, похоже, ничего не проходит.
WebClient client = WebClient.create(host);
WebClient.ResponseSpec responseSpec = client.post()
.uri("/v1/billing/subscriptions/"+subscriptionID+"/cancel")
.headers(h -> {
h.setBearerAuth(token);
//h.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//h.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
})
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
//.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
//.contentType(MediaType.APPLICATION_FORM_URLENCODED)
//.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromFormData(bodyValues))
.retrieve();
рабочий код был таким: создание тела объекта и использование fromValue в bodyinserter - responseBody имеет значение null в результате, но он отменяет идентификатор подписки
BasicDBObject body = new BasicDBObject();
body.put("reason", "xxx");
String bearerToken = generateAccessToken();
String token = bearerToken.split(" ")[1].trim();
WebClient client = WebClient.create(host);
WebClient.ResponseSpec responseSpec = client.post()
.uri("/v1/billing/subscriptions/"+subscriptionID+"/cancel")
.headers(h -> {
h.setBearerAuth(token);
})
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(body))
.retrieve();
String responseBody = responseSpec.bodyToMono(String.class).block();
System.out.println("responseSpec-- "+ responseSpec);
System.out.println("responseBody-- "+ responseBody);




В API-документе, на который вы ссылаетесь, говорится, что тело отмены — это json и содержит {«причина»: «слишком дорого»}. Вы отправляете форму. Отсюда 415: форма ≠ json.
Попробуй это:
String body = “{\”reason\”: \”too expensive\”}”;
WebClient client = WebClient.create(host);
WebClient.ResponseSpec responseSpec = client.post()
.uri("/v1/billing/subscriptions/"+subscriptionID+"/cancel")
.headers(h -> {
h.setBearerAuth(token);
})
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(body))
.retrieve();
Не более 415, поэтому я ответил на ваш вопрос. Может быть, идентификатор подписки шаткий ?? Добавьте код, чтобы получить тело ответа 400, распечатайте его и добавьте в новый вопрос.
У меня это заработало, если я изменил тело на объект -- BasicDBObject body = new BasicDBObject(); body.put ("причина", "xxx");
.contentType(MediaType.APPLICATION_JSON)
Я отредактировал свой ответ, чтобы также исправить 400.
Тело строки = "{\"причина\": \"слишком дорого\"}"; -- это работает, но это кажется беспорядочным способом создания объекта
Согласитесь, я бы определил класс с полем «причина» и разместил бы его, но такой формат не особо облегчает. Мое внимание сосредоточено на первоначальном вопросе, то есть разрешении 415 (а затем 400.
Можете ли вы поделиться документацией, которая привела вас к этому решению - я не нашел много примеров.
У меня большой опыт - я видел много ошибок 415, и они неизменно возникают, потому что форма была отправлена, но ожидался json или наоборот. В API-документе было довольно ясно о типе контента, я пропустил структуру полезной нагрузки поста, в основном потому, что это немного глупо — класс с одним полем. Одно поле может быть опубликовано. Поиск в Google «что вызывает ответ http 415» поможет вам довольно близко
Я имею в виду то, что примеры, которые я нашел, указывали, что тело должно быть MultiValueMap и завернуто в fromFormData - я не мог видеть четкого примера, который предлагал бы только fromValue.
MultiValueMap/fromFormData предназначен для серверной части, принимающей данные из html-форм. API с гораздо большей вероятностью примет json. Несколько примеров имплантации — codersee.com/spring-5-webclient-with-spring-boot и этот вопрос stackoverflow.com/questions/62073018/….
это возвращает ошибку 400 -- 400 Bad Request от POST