java實現微信App支付

廢話不多說,直接上代碼,微信的小程序,公衆號支付都大差不差,自行看文檔修改參數即可。

maven依賴:

<dependency>
    <groupId>com.github.wxpay</groupId>
    <artifactId>wxpay-sdk</artifactId>
    <version>0.0.3</version>
</dependency>

application.yml中配置微信相關參數:

wx:
  app:
    appId: wxdee12345681703e8
    mchId: 1512345671
    key: 86799C8812345675C82F3FE33FFE7EE3
    notifyUrl: https://test.shuai.com/wxPayCallback

引入wxpay依賴後需要實現裏面的微信配置類,將上面的微信相關的信息寫進去:

package com.bcn.yeyks.apppay.service.impl;

import com.github.wxpay.sdk.WXPayConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.InputStream;

/**
 * @Author fuchangshuai
 * @date 2019/3/13 5:29 PM
 */
@Service
public class WXPayConfigImpl implements WXPayConfig {
    @Value("${wx.app.appId}")
    String appID;

    @Value("${wx.app.key}")
    String key;

    @Value("${wx.app.mchId}")
    String mchID;

    @Override
    public String getAppID()
    {
        return appID;
    }

    @Override
    public String getMchID()
    {
        return mchID;
    }

    @Override
    public String getKey()
    {
        return key;
    }

    @Override
    public InputStream getCertStream()
    {
        return this.getClass().getResourceAsStream("/apiclient_cert.p12");
    }

    @Override
    public int getHttpConnectTimeoutMs()
    {
        return 2000;
    }

    @Override
    public int getHttpReadTimeoutMs()
    {
        return 10000;
    }
}

微信支付類:

package com.bcn.yeyks.apppay.service.impl;

import com.alibaba.fastjson.JSON;
import com.bcn.yeyks.apppay.service.WXAppPayService;
import com.bcn.yeyks.exception.ServiceException;
import com.bcn.yeyks.model.RefundRequestNo;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Author fuchangshuai
 * @date 2019/3/4 2:34 PM
 */
@Service
@Slf4j
public class WXAppPayServiceImpl implements WXAppPayService {
    @Autowired
    private WXPayConfig wxPayConfig;

    @Value("${wx.app.key}")
    String key;

    @Value("${wx.app.notifyUrl}")
    String notify_url;

    @Value("${wx.app.vipNotifyUrl}")
    String vip_notify_url;

    @Value("${wx.app.appId}")
    String appId;

    @Value("${wx.app.mchId}")
    String mch_id;

    @Override
    public String pay(Integer totalFee, String orderNo, String ip) {
        log.info("微信app支付");
        Map<String, String> map = wxPay(orderNo, totalFee, ip);
        return JSON.toJSONString(map);
    }

    @Override
    public Boolean refund(Integer refundFee, Integer totalFee, String orderNo) {
        log.info("微信退款");
        return wxRefund(refundFee, totalFee, orderNo);
    }

    private Map<String, String> wxPay(String orderNO, Integer payAmount, String ip) {
        try {
            Map<String, String> map = new LinkedHashMap<>();
            String body = "訂單支付";
            String nonce_str = WXPayUtil.generateNonceStr();
            String total_fee = String.valueOf(payAmount);
            map.put("body", body);
            map.put("nonce_str", nonce_str);
            map.put("out_trade_no", orderNO);
            map.put("total_fee", total_fee);
            map.put("spbill_create_ip", ip);
            map.put("notify_url", notify_url);
            map.put("trade_type", "APP");
            WXPay pay = new WXPay(wxPayConfig);
            Map<String, String> returnMap = pay.unifiedOrder(map);
            Map<String, String> resultMap = new LinkedHashMap<>();
            resultMap.put("appid", appId);
            resultMap.put("noncestr", nonce_str);
            resultMap.put("package", "Sign=WXPay");
            resultMap.put("partnerid", mch_id);
            resultMap.put("prepayid", returnMap.get("prepay_id"));
            resultMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
            StringBuilder result = new StringBuilder();
            for (Map.Entry<String, String> entry : resultMap.entrySet()) {
                result.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            result.append("key=").append(key);
            resultMap.put("sign", DigestUtils.md5Hex(result.toString()).toUpperCase());

            return resultMap;
        } catch (Exception e) {
            log.info("微信支付失敗{}", Arrays.toString(e.getStackTrace()));
            throw new ServiceException("微信支付異常");
        }
    }

    private Boolean wxRefund(Integer refundFee, Integer totalFee, String orderNo) {
        try {
            String outRequestNo = orderNo + RefundRequestNo.outNo;
            String refundAmount = String.valueOf(refundFee);
            String totalAmount = String.valueOf(totalFee);
            Map<String, String> map = new LinkedHashMap<>();
            String nonce_str = WXPayUtil.generateNonceStr();
            map.put("nonce_str", nonce_str);
            map.put("out_trade_no", orderNo);
            map.put("out_refund_no", outRequestNo);
            map.put("total_fee", totalAmount);
            map.put("refund_fee", refundAmount);
            WXPay pay = new WXPay(wxPayConfig);
            Map<String, String> resutlMap = pay.refund(map);
            String resultCode = resutlMap.get("result_code") == null ? "FAIL" : resutlMap.get("result_code");
            String resultRefundFee = resutlMap.get("refund_fee") == null ? "FAIL" : resutlMap.get("refund_fee");
            if ("SUCCESS".equals(resultCode) && resultRefundFee.equals(refundAmount)) {
                return true;
            }
        } catch (Exception e) {
            log.info("微信退款失敗{}", Arrays.toString(e.getStackTrace()));
            return false;
        }
        return false;
    }
}

 

微信支付返回的回調類:

 

package com.bcn.yeyks.apppay.controller;

import com.bcn.yeyks.dal.domain.OrderInfo;
import com.bcn.yeyks.dal.domain.VipOrder;
import com.bcn.yeyks.exception.ServiceException;
import com.bcn.yeyks.service.OrderService;
import com.bcn.yeyks.service.VipOrderService;
import com.bcn.yeyks.wxpay.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author fuchangshuai
 * @date 2019/3/11 1:48 PM
 */
@RestController
@Slf4j
public class WxPayCallbackController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private VipOrderService vipOrderService;

    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    @RequestMapping(value = "/wxPayCallback", method = RequestMethod.POST)
    public String wxPayCallback(HttpServletRequest request) {
        log.info("微信支付回調");
        try {
            // 讀取參數
            // 解析xml成map
            Map<String, String> map = WXPayUtil.xmlToMap(getParam(request));
            log.info("微信支付回調返回的信息{}", map);
            check(map);//該處讀者自行校驗(驗證訂單號,付款金額等是否正確)
            String orderNo = map.get("out_trade_no");
            String resultCode = map.get("result_code");
            // 另起線程處理業務
            log.info("另起線程處理業務");
            executorService.execute(() -> {
                // 支付成功
                if (resultCode.equals("SUCCESS")) {
                    log.info("支付成功");
                    // TODO 自己的業務邏輯
                } else {
                    log.info("支付失敗");
                    // TODO 自己的業務邏輯
                }
            });
            if (resultCode.equals("SUCCESS")) {
                return setXml("SUCCESS", "OK");
            } else {
                return setXml("fail", "付款失敗");
            }
        } catch (ServiceException e) {
            log.info("微信支付回調發生異常{}", e.getMessage());
            return setXml("fail", "付款失敗");
        } catch (Exception e) {
            log.info("微信支付回調發生異常{}", e.getLocalizedMessage());
            return setXml("fail", "付款失敗");
        }
    }

    private String getParam(HttpServletRequest request) throws IOException {
        // 讀取參數
        InputStream inputStream;
        StringBuilder sb = new StringBuilder();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        return sb.toString();
    }

    private void check(Map<String, String> params) throws ServiceException {
        String outTradeNo = params.get("out_trade_no");
        // 1、商戶需要驗證該通知數據中的out_trade_no是否爲商戶系統中創建的訂單號,
        OrderInfo order = orderService.selectOrderByOrderNo(outTradeNo);
        if (order == null) {
            throw new ServiceException("out_trade_no錯誤");
        }

        // 2、判斷total_amount是否確實爲該訂單的實際金額(即商戶訂單創建時的金額),
        Integer totalAmount = Integer.valueOf(params.get("total_fee"));
        log.info("totalAmount{}", totalAmount);
        if (!totalAmount.equals(order.getSnapshotTotalFee())) {
            throw new ServiceException("total_amount錯誤");
        }
    }

    // 通過xml發給微信消息
    private static String setXml(String return_code, String return_msg) {
        SortedMap<String, String> parameters = new TreeMap<>();
        parameters.put("return_code", return_code);
        parameters.put("return_msg", return_msg);
        try {
            return WXPayUtil.mapToXml(parameters);
        } catch (Exception e) {
            log.error("返回微信消息時map轉xml失敗");
            return "<xml><return_code><![CDATA[" + return_code + "]]>" + "</return_code><return_msg><![CDATA[" + return_msg
                    + "]]></return_msg></xml>";
        }
    }

}

到這裏微信支付已經完成,按照上面的步驟,完全可以實現微信的app支付,下一篇將介紹支付寶的app支付

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章