Java實現(xiàn)支付寶充值

支付寶SDK依賴

        <!--支付寶-->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>3.3.4.ALL</version>
        </dependency>

支付寶參數(shù)配置類

@Component
@Configuration
public class AliDevPayConfig implements Serializable {
    /**
     * 支付寶服務器主動通知商戶服務器里指定的頁面http/https路徑
     * 異步請求,地址必須是公網(wǎng)可以訪問的才行,不能有任何參數(shù)
     * 例如:項目發(fā)布地址/本項目名/接口名
     */
    public static String NOTIFY_URL;

    public static String RETURN_URL;

    @Value("${alipay.aliPayReturnUrl}")
    public void setReturnUrl(String returnUrl) {
        RETURN_URL = returnUrl;
    }
    @Value("${alipay.aliPayNotifyUrl}")
    public void setNotifyUrl(String notifyUrl) {
        NOTIFY_URL = notifyUrl;
    }

    public String getNotifyUrl() {
        return NOTIFY_URL;
    }
    public String getReturnUrl() {
        return RETURN_URL;
    }

    /**支付寶分配給開發(fā)者的應用ID*/
    public static String aliPayAppId = "開發(fā)者id";
    /**支付寶網(wǎng)關(guān)*/
    public static String aliPayGateWay = "https://openapi.alipay.com/gateway.do";

    /**私鑰*/
    public static String aliPayPrivateKey = "你的私鑰";
    /**支付寶公鑰*/
    public static String aliPayPublicKey = "你的公鑰";

    /**僅支持JSON*/
    public static String FORMAT = "JSON";
    /**請求使用的編碼格式,如utf-8,gbk,gb2312等*/
    public static String CHARSET = "utf-8";
    /**商戶生成簽名字符串所使用的簽名算法類型,目前支持RSA2和RSA,推薦使用RSA2*/
    public static String SIGN_TYPE = "RSA2";
}

因為我的項目有多個環(huán)境,會有多個對應的配置文件,所以我選擇用@Value注入的方式。
配置文件的url配置如下:

alipay:
  aliPayNotifyUrl: 異步回調(diào)url
  aliPayReturnUrl: 同步回調(diào)url

Controller

    @Resource
    PayService payService;

    @RequestMapping(value = "/ali", method = RequestMethod.POST)
    @ApiOperation(value="[支付寶]充值")
    public Result<String> alipayTopup(@RequestBody AliPayRechargeDTO aliPayRechargeDTO){
        return Result.getSuccess(payService.saveAliPayRechangeBill(aliPayRechargeDTO));
    }


    @RequestMapping(value = "/alipaynotice", method = RequestMethod.POST)
    @ApiOperation(value="[支付寶專用]支付寶充值接口異步回調(diào)接口")
    public String paynotice(HttpServletRequest request){
        return payService.alipayNotify(request);
    }

DTO對象傳入你所需要的參數(shù),比如金額,賬戶id等等。

Service

@Slf4j
@Service
public class PayService{

    public String saveAliPayRechangeBill(AliPayRechargeDTO rechargeDTO){
        BigDecimal totalAmount = rechargeDTO.getRechargeTotalAmount();

        //實例化客戶端(參數(shù):網(wǎng)關(guān)地址、商戶appid、商戶私鑰、格式、編碼、支付寶公鑰、加密類型),為了取得預付訂單信息
        AlipayClient alipayClient = new DefaultAlipayClient(AliDevPayConfig.aliPayGateWay, AliDevPayConfig.aliPayAppId,
                AliDevPayConfig.aliPayPrivateKey, AliDevPayConfig.FORMAT, AliDevPayConfig.CHARSET,
                AliDevPayConfig.aliPayPublicKey, AliDevPayConfig.SIGN_TYPE);
        //實例化具體API對應的request類,類名稱和接口名稱對應,當前調(diào)用接口名稱:alipay.trade.app.pay
        AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();


        //SDK已經(jīng)封裝掉了公共參數(shù),這里只需要傳入業(yè)務參數(shù)。以下方法為sdk的model入?yún)⒎绞?        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

        //對一筆交易的具體描述信息。如果是多種商品,請將商品描述字符串累加傳給body。
        model.setBody("xx商品介紹");
        //商品名稱
        model.setSubject("xx商品");
        //商戶訂單號(根據(jù)業(yè)務需求自己生成)
        model.setOutTradeNo("你自己業(yè)務賬單的id");
        //交易超時時間 這里的30m就是30分鐘
        model.setTimeoutExpress("30m");
        //支付金額 后面保留2位小數(shù)點..不能超過2位
        model.setTotalAmount(totalAmount.toString());
        //銷售產(chǎn)品碼(固定值)
        model.setProductCode("QUICK_MSECURITY_PAY");

        ali_request.setBizModel(model);



        //異步回調(diào)地址(后臺)
        ali_request.setNotifyUrl(AliDevPayConfig.NOTIFY_URL);
        log.info("Alipay異步通知的地址為:" + ali_request.getNotifyUrl());

        try{
            // 這里和普通的接口調(diào)用不同,使用的是sdkExecute
            //返回支付寶訂單信息(預處理)
            AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(ali_request);
            //就是orderString 可以直接給APP請求,無需再做處理。
            String alipayTransferId = alipayTradeAppPayResponse.getBody();
            log.info("需要返回給支付寶的數(shù)據(jù) alipayTransferId:" + alipayTransferId);
            return alipayTransferId;
        }catch (AlipayApiException e){
            e.printStackTrace();
        }
        return null;
    }


    public String alipayNotify(HttpServletRequest request) {
        log.info("支付寶異步返回支付結(jié)果開始");

        //1.從支付寶回調(diào)的request域中取值
        //獲取支付寶返回的參數(shù)集合
        Map<String, String[]> aliParams = request.getParameterMap();

        log.info("支付寶Post過來的反饋信息:" + aliParams.toString());

        //用以存放轉(zhuǎn)化后的參數(shù)集合
        Map<String, String> conversionParams = new HashMap<String, String>();
        for (Iterator<String> iter = aliParams.keySet().iterator(); iter.hasNext();) {
            String key = iter.next();
            String[] values = aliParams.get(key);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 亂碼解決,這段代碼在出現(xiàn)亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉(zhuǎn)化
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
            conversionParams.put(key, valueStr);
        }

        log.info("支付寶返回參數(shù)集合:"+conversionParams);
        String status=aliPayCheck(conversionParams);
        return status;
    }

    public String aliPayCheck(Map conversionParams){
        log.info("=支付寶異步請求邏輯處理=");
        //簽名驗證(對支付寶返回的數(shù)據(jù)驗證,確定是支付寶返回的)
        boolean signVerified = false;
        try {
            //調(diào)用SDK驗證簽名
            String alipayPublicKey = AliDevPayConfig.aliPayPublicKey;
            String charset = AliDevPayConfig.CHARSET;
            String signType = AliDevPayConfig.SIGN_TYPE;

            signVerified = AlipaySignature.rsaCheckV1(conversionParams, alipayPublicKey, charset, signType);
            //對驗簽進行處理.
            if (signVerified) {
                log.info("+++++++++++支付寶回調(diào)簽名認證成功+++++++++++");
                // 按照支付結(jié)果異步通知中的描述,對支付結(jié)果中的業(yè)務內(nèi)容進行1\2\3\4二次校驗,校驗成功后在response中返回success,校驗失敗返回failure 支付寶官方建議校驗的值(out_trade_no、total_amount、sellerId、app_id)
                //驗簽通過 獲取交易狀態(tài)
                String tradeStatus = (String)conversionParams.get("trade_status");

                //只處理支付成功的訂單: 修改交易表狀態(tài),支付成功
                //只有交易通知狀態(tài)為TRADE_SUCCESS或TRADE_FINISHED時,支付寶才會認定為買家付款成功。
                if (tradeStatus.equals("TRADE_SUCCESS") ||tradeStatus.equals("TRADE_FINISHED")) {
                    //TODO 獲取支付寶通知完成充值后續(xù)業(yè)務

                    //交易成功 獲取商戶賬單id
                    String billId = (String) conversionParams.get("out_trade_no");
                    //支付寶交易流水號
                    String ali_pay_no = (String) conversionParams.get("trade_no");
                    

                    //TODO 修改業(yè)務訂單信息
                    //TODO 余額到賬,消息推送

                    return "success";
                } else {
                    return "fail";
                }
            }else{  //驗簽不通過
                log.info("++驗簽不通過 !++");
                return "fail";
            }
        } catch (AlipayApiException e) {
            log.info("+++驗簽失敗 !+++");
            e.printStackTrace();
        }
        return "fail";
    }

}

以上saveAliPayRechangeBill方法返回的類型如下

app_id=2015052600090779&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22seller_id%22%3A%22%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%22IQJZSRC1YMQB5HU%22%7D&charset=utf-8&format=json&method=alipay.trade.app.pay&notify_url=http%3A%2F%2Fdomain.merchant.com%2Fpayment_notify&sign_type=RSA2&timestamp=2016-08-25%2020%3A26%3A31&version=1.0&sign=cYmuUnKi5QdBsoZEAbMXVMmRWjsuUj%2By48A2DvWAVVBuYkiBj13CFDHu2vZQvmOfkjE0YqCUQE04kqm9Xg3tIX8tPeIGIFtsIyp%2FM45w1ZsDOiduBbduGfRo1XRsvAyVAv2hCrBLLrDI5Vi7uZZ77Lo5J0PpUUWwyQGt0M4cj8g%3D

以上結(jié)果等價于如下,但上面才是正常的返回結(jié)果。

body="test"&_input_charset="UTF-8"&it_b_pay="1d"&total_fee="1"&subject="test"&notify_url="http://www.bejson.com/api/alipay/testpayotify.php"&service="mobile.securitypay.pay"&seller_id="cw@bejson.com"&partner="2088301"&out_trade_no="2088301971894011"&payment_type="1"&show_url="http://www.dcloud.io/helloh5/"&sign="RtUKAGMfelb5sl2az4YKhxst051l94FSkpk9xoD91Hbpr2PKnWjHIafTWqNLyxGibde%2BKwcq9Y8cDN0qU%2FsO6hXjch0B4GaMJHBxZQM%2FnJK2YGxPPOWFKKL5rBKVJ%2BrX4OImfSQIyKKUpAEFG6uFfek2hh%2FPFJSXk2Phvmrb8U%3D"&sign_type="RSA"

調(diào)用時,請核對所有支付寶所必要的參數(shù),參考支付寶參數(shù)

至此就已經(jīng)差不多完成支付寶的接入了,如果有其他問題可以百度或者留言,如果有什么錯誤,歡迎多多指正批評。:)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容