1. 程式人生 > 其它 >洛谷 P3374 【模板】樹狀陣列 1

洛谷 P3374 【模板】樹狀陣列 1

技術標籤:支付java

支付寶支付(證書模式)前提:
在這裡插入圖片描述

這三個證書先準備好,獲取的步驟就不用說了;

現在支付寶已經很貼心的幫我們封裝好了各種api,直接在pom檔案裡面引入以下依賴就行了。

com.alipay.sdk
alipay-easysdk
${alipay-easysdk.version}

<alipay-easysdk.version>2.2.0</alipay-easysdk.version>

這些做好了直接呼叫api就行了

一、先初始化客戶端工廠類,全域性初始化一次就夠了:
import com.alipay.easysdk.factory.Factory;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**

  • 啟動時初始化一下支付寶
    */
    @Component
    public class AliPayFactoryInit {
    @Resource
    private AlipayConfig alipayConfig;

    @PostConstruct
    public void AliPayFactoryInit() {
    //1.全域性只用設定引數一次
    Factory.setOptions(alipayConfig.Config());

    }

}

二、配置檔案
import com.alipay.easysdk.kernel.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AlipayConfig {

@Value("${alipay.gatewayHost}")
private String gatewayHost;

@Value("${alipay.appId}")
private String appId;

@Value("${alipay.merchantPrivateKey}")
private String merchantPrivateKey;

@Value("${alipay.merchantCertPath}")
private String merchantCertPath;

@Value("${alipay.alipayCertPath}")
private String alipayCertPath;

@Value("${alipay.alipayRootCertPath}")
private String alipayRootCertPath;


@Value("${alipay.notifyUrl}")
private String notifyUrl;

@Value("${alipay.encryptKey}")
private String encryptKey;


@Bean
public Config Config() {
    Config config = new Config();
    config.protocol = "https";
    config.gatewayHost = gatewayHost;
    config.signType = "RSA2";
    config.appId = appId;
    // 為避免私鑰隨原始碼洩露,推薦從檔案中讀取私鑰字串而不是寫入原始碼中
    config.merchantPrivateKey = merchantPrivateKey;
    //注:證書檔案路徑支援設定為檔案系統中的路徑或CLASS_PATH中的路徑,優先從檔案系統中載入,載入失敗後會繼續嘗試從CLASS_PATH中載入
    config.merchantCertPath = merchantCertPath;
    config.alipayCertPath = alipayCertPath;
    config.alipayRootCertPath = alipayRootCertPath;
    //注:如果採用非證書模式,則無需賦值上面的三個證書路徑,改為賦值如下的支付寶公鑰字串即可
    // config.alipayPublicKey = "<-- 請填寫您的支付寶公鑰,例如:MIIBIjANBg... -->";
    //可設定非同步通知接收服務地址(可選)
    config.notifyUrl = notifyUrl;
    //可設定AES金鑰,呼叫AES加解密相關介面時需要(可選)
    config.encryptKey = encryptKey;
    return config;
}

}

三、支付業務類
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.common.models.AlipayTradeCloseResponse;
import com.alipay.easysdk.payment.common.models.AlipayTradeCreateResponse;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.alipay.easysdk.payment.wap.models.AlipayTradeWapPayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class DoAliPayReqImpl implements DoAliPayReq {

/**
 * 預支付
 *
 * @param subject     訂單名稱
 * @param outTradeNo  商戶訂單號
 * @param totalAmount 支付金額
 * @return
 */
public ApiResult createPay(String subject, String outTradeNo, String totalAmount, String quitUrl, String returnUrl) {
    try {
        // 2. 發起API呼叫
        log.info("支付金額為:{}", totalAmount);
        log.info("支付訂單號為:{}", outTradeNo);
        log.info("退出返回為為:{}", quitUrl);
        log.info("返回為:{}", returnUrl);
        log.info("商品名稱:{}", subject);
        AlipayTradeWapPayResponse response =
                Factory.Payment.Wap().pay(subject, outTradeNo, totalAmount, quitUrl, returnUrl);
        // 3. 處理響應或異常
        log.error("返回跳轉連結:{}", response.getBody());
        if (ResponseChecker.success(response)) {
            return ApiResult.ok(response.getBody());
        } else {
            log.error("呼叫失敗");
            return ApiResult.fail();
        }
    } catch (Exception e) {
        log.error("呼叫遭遇異常,原因:" + e.getMessage());
        return ApiResult.fail(e.getMessage());

    }
}


/**
 * 支付回撥
 *
 * @param request
 * @param response
 * @return
 */
public String notify(HttpServletRequest request, HttpServletResponse response) {
    try {
        //1.從支付寶回撥的request域中取值
        Map<String, String[]> requestParams = request.getParameterMap();
        Map<String, String> params = new HashMap<>();
        for (String name : requestParams.keySet()) {
            params.put(name, request.getParameter(name));
        }
        //2.簽名驗證
        Boolean aBoolean = Factory.Payment.Common().verifyNotify(params);
        if (!aBoolean) {
            log.error("verifyNotify failed! params={}", params);
            return PayConstant.ALI_FAIL;
        }
        //訂單狀態
        String tradeStatus = params.get(PayConstant.ALI_TRADE_STATUS);
        //商戶訂單號
        String outTradeNo = params.get(PayConstant.ALI_OUT_TRADE_NO);
        //流水號
        String tradeNo = params.get(PayConstant.ALI_TRADE_NO);
        //3 判斷狀態
        if (!tradeStatus.equals(PayConstant.TRADE_SUCCESS)) {
            log.error("order not pay succ! orderInfo={}", params);
            return PayConstant.ALI_SUCCESS;
        }
        //4 更新訂單
        if (!updateMainOrder) {
            log.error("updateMainOrderByPayOrderId failed! request={}", params);
            return PayConstant.ALI_FAIL;
        }
        log.info("payinfo process succ! request={}", params);
        return PayConstant.ALI_SUCCESS;
    } catch (Exception e) {
        log.error("回撥介面異常,原因:{}", e.getMessage());
    }
    return PayConstant.ALI_FAIL;
}

/**
 * 關閉訂單
 *
 * @param outTradeNo 商戶訂單號
 * @return
 */
public void closePay(String outTradeNo) {
    try {
        // 2. 發起API呼叫
        log.error("關閉訂單號為:{}", outTradeNo);
        AlipayTradeCloseResponse close = Factory.Payment.Common().close(outTradeNo);
        // 3. 處理響應或異常
        log.error("返回訂單號為:{}", close.getMsg());
    } catch (Exception e) {
        log.error("呼叫遭遇異常,原因:" + e.getMessage());
    }
}


/**
 * 退款介面
 *
 * @return
 */
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 1.5))
public String refund(String outTradeNo, String refundAmount) throws Exception {
    try {
        log.error("refund,時間:" + LocalTime.now());
        // 2. 發起API呼叫
        log.error("alipay關閉訂單號為:{}", outTradeNo);
        AlipayTradeRefundResponse refund = Factory.Payment.Common().refund(outTradeNo, refundAmount);
        // 3. 處理響應或異常
        log.error("alipay退款返回為:{}", refund.getMsg());
        if (ResponseChecker.success(refund)) {
            return refund.getCode();
        }
        return null;
    } catch (Exception e) {
        log.error("alipay呼叫遭遇異常,原因:{}", e.getMessage());
        throw new Exception("alipay呼叫遭遇異常");
    }
}

@Recover
public String recover(Exception e) {
    System.out.println("alipay重試次數結束後還有異常,回撥方法開始執行");
    log.error("alipay重試次數結束後還有異常,回撥方法開始執行");
    //可呼叫其餘的方法
    return null;
}

/**

  • 獲小程式取pid
  • @param params
  • @param httpRequest
  • @return
  • @throws Exception
    */
    @Override
    public ApiResult getOpenId(GetOpenIdReqeust params, HttpServletRequest httpRequest) {
    try {
    // 2. 配置
    log.error(“支付寶小程式code為:{}”, params.getCode());
    AlipaySystemOauthTokenResponse token = Factory.Base.OAuth().getToken(params.getCode());
    // 3. 處理響應或異常
    log.error(“返回支付寶小程式userId為:{}”, token.getUserId());
    if (ResponseChecker.success(token)) {
    return ApiResult.ok(token.getUserId());
    } else {
    log.error(“呼叫失敗”);
    return ApiResult.fail(token.getSubMsg());
    }
    } catch (Exception e) {
    log.error(“呼叫遭遇異常,原因:” + e.getCause());
    return ApiResult.fail(e.getMessage());
    }
    }

/**

  • 獲取手機號
  • @param params
  • @return
  • @throws Exception
    */
    public ApiResult getPhone(GetPhoneVo params) {
    try {
    String response = params.getContent();
    //1. 獲取驗籤和解密所需要的引數
    Map<String, String> openapiResult = JSON.parseObject(response,
    new TypeReference<Map<String, String>>() {
    }, Feature.OrderedField);
    String signType = “RSA2”;
    String charset = “UTF-8”;
    String encryptType = “AES”;
    String sign = openapiResult.get(“sign”);
    String content = openapiResult.get(“response”);
    //如果密文的
    boolean isDataEncrypted = !content.startsWith("{");
    boolean signCheckPass = false;
    //2. 驗籤
    String signContent = content;
    String signVeriKey = aliAppletsConfig.getPublicKey();
    String decryptKey = aliAppletsConfig.getMerchantPrivateKey();
    //如果是加密的報文則需要在密文的前後新增雙引號
    if (isDataEncrypted) {
    signContent = “”" + signContent + “”";
    }
    signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
    if (!signCheckPass) {
    //驗籤不通過(異常或者報文被篡改),終止流程(不需要做解密)
    return ApiResult.fail(response);
    }
    //3. 解密
    String plainData = null;
    if (isDataEncrypted) {
    plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
    } else {
    plainData = content;
    }
    //json序列化
    JSONObject object = JSONObject.parseObject(plainData);
    if (object != null && “10000”.equals(object.getString(“code”))) {
    return ApiResult.fail(plainData);
    }
    String mobile = object.get(“mobile”).toString();
    return ApiResult.ok(mobile);
    } catch (Exception e) {
    log.error(“解密遭遇異常,原因:” + e.getCause());
    return ApiResult.fail(“解密遭遇異常”);
    }
    }

}