PayServiceClient.java 4.75 KB
package com.infoloop.tianting.service.client;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.infoloop.tianting.config.BusinessConfig;
import com.infoloop.tianting.model.dto.PayDTO.PayInformRequestDto;
import com.infoloop.tianting.model.dto.PayDTO.PayResponseDto;
import com.infoloop.tianting.model.dto.PayDTO.ThirdPartyPayInformRequestDto;
import com.infoloop.tianting.model.dto.PaymentCallbackDTO;
import com.infoloop.tianting.utils.DateUtil;
import com.infoloop.tianting.utils.EncryptionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;


@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PayServiceClient {

    private final RestTemplate restTemplate;

    private final BusinessConfig businessConfig;

    @Value("${payment.client-id:Order0001}")
    private String clientId;

    private final XmlMapper xmlMapper = new XmlMapper();

    public PayResponseDto payInform(PayInformRequestDto payRequestDto) {
        String url = businessConfig.getPayUrl();
        String requestDate = DateUtil.formatDate(LocalDateTime.now(), DateUtil.YMDHMS);
        ThirdPartyPayInformRequestDto jsonData = buildRequestData(payRequestDto, requestDate);
        String jsonDataString;
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
            jsonDataString = objectMapper.writeValueAsString(jsonData);
        } catch (JsonProcessingException e) {
            log.error("Failed to serialize request data", e);
            throw new IllegalArgumentException("支付通知失败: JSON 解析错误");
        }
        HttpEntity<String> requestEntity = new HttpEntity<>(jsonDataString, createHeaders());
        log.info("payInform request: {}", jsonDataString);
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        return processResponse(responseEntity);
    }

    private ThirdPartyPayInformRequestDto buildRequestData(PayInformRequestDto payRequestDto, String requestDate) {
        ThirdPartyPayInformRequestDto jsonData = new ThirdPartyPayInformRequestDto();
        jsonData.setClientId(clientId);
        jsonData.setTradeId(payRequestDto.getOrderId());
        jsonData.setRequestDate(requestDate);
        jsonData.setRequestSource("OFWXApplet");
        jsonData.setPayerOpenId(payRequestDto.getOpenId());
        jsonData.setHospitalCode(payRequestDto.getHospitalCode());
        jsonData.setPID(payRequestDto.getPhone());
        jsonData.setRemark("");
        jsonData.setTransAmount(payRequestDto.getPrice());
        jsonData.setTradeDesc("");
        jsonData.setSign(EncryptionUtil.sha1Encryption(clientId + payRequestDto.getOrderId() + requestDate + clientId));
        return jsonData;
    }

    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return headers;
    }

    private PayResponseDto processResponse(ResponseEntity<String> responseEntity) {
        if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) {
            log.error("payInform failed with response: {}", responseEntity.getBody());
            throw new IllegalArgumentException("支付通知失败");
        }
        try {
            log.info("processResponse response: {}", responseEntity.getBody());
            return xmlMapper.readValue(responseEntity.getBody(), PayResponseDto.class);
        } catch (Exception e) {
            log.error("Failed to parse XML response", e);
            throw new RuntimeException("支付通知结果解析失败", e);
        }
    }

    public void callback(PaymentCallbackDTO payInformRequestDto) {
        log.info("callback: {}", payInformRequestDto);

    }
}