springboot集成微信app支付

一、準備工作(以下信息需要自行開通和申請):

    public static final String APP_ID = "";//app的id 需要app應用
    public static final String KEY = "";//api密鑰 商戶賬戶信息裏面去獲取
    public static final String MCH_ID = "";//商戶的id,需要開通商戶

maven項目添加依賴:

		<!-- 微信支付 -->
		<dependency>
			<groupId>com.github.wxpay</groupId>
			<artifactId>wxpay-sdk</artifactId>
			<version>0.0.3</version>
		</dependency>

二、開發流程:

整個流程我們只需要兩個接口即可:

1.微信支付的統一下單接口(本地項目請求微信):

接口api請點擊這裏

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

2.微信支付後的通知接口,是我們向外提供的(微信請求本地項目):接口地址自行定義

 

三、代碼:我使用的springboot restful接口方式,詳解請看註釋

service層:


import java.util.Map;

/**
 * 
 * @類名稱 WeixinService.java
 * @類描述 <pre>微信相關</pre>
 * @作者  yw  [email protected]
 * @創建時間 2020年4月29日 下午4:25:10
 * @版本 5.0.0
 *
 * @修改記錄
 * <pre>
 *     版本                       修改人 		修改日期 		 修改內容描述
 *     ----------------------------------------------
 *     5.0.0 	yw 	2020年4月29日             
 *     ----------------------------------------------
 * </pre>
 */
public interface WeixinService {

	/**
	 * 
	 * @方法名稱 payBack
	 * @功能描述 <pre>回調接口</pre>
	 * @作者    yw
	 * @創建時間 2020年5月22日 下午12:50:15
	 * @param resXml
	 * @return
	 */
    String payBack(String resXml);

    /**
     * 
     * @param order 
     * @方法名稱 doUnifiedOrder
     * @功能描述 <pre>統一下單</pre>
     * @作者    yw
     * @創建時間 2020年5月22日 下午12:50:26
     * @return
     * @throws Exception
     */
    Map<String, String> doUnifiedOrder(Order order) throws Exception;
    
}

service層實現(以下代碼已刪除了業務處理部分,需要自己添加自己項目的業務處理):


import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @類名稱 WeixinServiceImpl.java
 * @類描述 <pre>微信 支付</pre>
 * @作者  yw  [email protected]
 * @創建時間 2020年5月22日 下午12:51:13
 * @版本 5.0.0
 *
 * @修改記錄
 * <pre>
 *     版本                       修改人 		修改日期 		 修改內容描述
 *     ----------------------------------------------
 *     5.0.0 	yw 	2020年5月22日             
 *     ----------------------------------------------
 * </pre>
 */
@Service
@Slf4j
public class WeixinServiceImpl implements WeixinService {
	
    public static final String HOST_IP = "";//回調的服務器ip
    public static final String NOTIFY_URL = "";//回調的地址,注意:外網可以訪問
    public static final String TRADE_TYPE_APP = "APP";

    @Autowired
    OrderService orderService;//自己業務的處理服務
   
    @Override
    public String payBack(String resXml) {
        WXConfigUtil config = null;
        try {
            config = new WXConfigUtil();
        } catch (Exception e) {
            e.printStackTrace();
        }
        WXPay wxpay = new WXPay(config);
        String xmlBack = "";
        Map<String, String> notifyMap = null;
        try {
            notifyMap = WXPayUtil.xmlToMap(resXml);         // 調用官方SDK轉換成map類型數據
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {//驗證簽名是否有效,有效則進一步處理

                String return_code = notifyMap.get("return_code");//狀態
                String out_trade_no = notifyMap.get("out_trade_no");//商戶訂單號
                if (return_code.equals("SUCCESS")) {
                    if (out_trade_no != null) {
                        // 注意特殊情況:訂單已經退款,但收到了支付結果成功的通知,不應把商戶的訂單狀態從退款改成支付成功
                        // 注意特殊情況:微信服務端同樣的通知可能會多次發送給商戶系統,所以數據持久化之前需要檢查是否已經處理過了,處理了直接返回成功標誌
                    	//業務處理 以下進行業務處理(比如修改訂單狀態信息等)
                        log.info("微信手機支付回調成功訂單號:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                    } else {
                        log.info("微信手機支付回調失敗訂單號:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[報文爲空]]></return_msg>" + "</xml> ";
                    }
                }
                return xmlBack;
            } else {
                // 簽名錯誤,如果數據裏沒有sign字段,也認爲是簽名錯誤
                //失敗的數據要不要存儲?
                log.error("手機支付回調通知簽名錯誤");
                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[報文爲空]]></return_msg>" + "</xml> ";
                return xmlBack;
            }
        } catch (Exception e) {
            log.error("手機支付回調通知失敗", e);
            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[報文爲空]]></return_msg>" + "</xml> ";
        }
        return xmlBack;
    }

    /**
     * 
     * @方法名稱 doUnifiedOrder
     * @功能描述 <pre>統一下單接口具體實現</pre>
     * @作者    yw
     * @創建時間 2020年5月22日 下午4:30:44
     * @param order 參數可以根據自己定義
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> doUnifiedOrder(Order order) throws Exception {
        try {
            WXConfigUtil config = new WXConfigUtil();
            WXPay wxpay = new WXPay(config);
            Map<String, String> data = new HashMap<>();
            //生成商戶訂單號,不可重複
            data.put("appid", WXConfigUtil.APP_ID);
            data.put("mch_id", WXConfigUtil.MCH_ID);
            data.put("nonce_str", WXPayUtil.generateNonceStr());
            String body = "手機支付";
            data.put("body", body);
            data.put("out_trade_no", order.getOrderNo());//訂單號
            data.put("total_fee", "1");//設置金額1分
            //自己的服務器IP地址
            data.put("spbill_create_ip", HOST_IP);
            //異步通知地址(請注意必須是外網)
            data.put("notify_url", NOTIFY_URL);
            //交易類型
            data.put("trade_type", TRADE_TYPE_APP);
            //附加數據,在查詢API和支付通知中原樣返回,該字段主要用於商戶攜帶訂單的自定義數據
            data.put("attach", "");
            data.put("sign", WXPayUtil.generateSignature(data, WXConfigUtil.KEY,
                    WXPayConstants.SignType.MD5));
            //使用官方API請求預付訂單
            Map<String, String> response = wxpay.unifiedOrder(data);
            if ("SUCCESS".equals(response.get("return_code"))) {//主要返回以下5個參數
                Map<String, String> param = new HashMap<>();
                param.put("appid", WXConfigUtil.APP_ID);
                param.put("partnerid",response.get("mch_id"));
                param.put("prepayid",response.get("prepay_id"));
                param.put("package","Sign=WXPay");
                param.put("noncestr",WXPayUtil.generateNonceStr());
                param.put("timestamp",System.currentTimeMillis()/1000+"");
                param.put("sign",WXPayUtil.generateSignature(param, WXConfigUtil.KEY,
                        WXPayConstants.SignType.MD5));
                return param;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("下單失敗");
        }
        throw new Exception("下單失敗");
    }
}

controller層:



import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;



import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @類名稱 WeixinRestController.java
 * @類描述 <pre>微信app支付</pre>
 * @作者  yw  [email protected]
 * @創建時間 2020年5月22日 下午4:04:19
 * @版本 5.0.0
 *
 * @修改記錄
 * <pre>
 *     版本                       修改人 		修改日期 		 修改內容描述
 *     ----------------------------------------------
 *     5.0.0 	yw 	2020年5月22日             
 *     ----------------------------------------------
 * </pre>
 */
@Slf4j
@Api(value="微信",tags={"微信"})
@RequestMapping("/weixin/")
@RestController
public class WeixinRestController{
	
	@Autowired
	WeixinService weixinService;
	
	/**
	 * 
	 * @方法名稱 wxAdd
	 * @功能描述 <pre>微信統一下單- 前端發起下單 比如web ios android</pre>
	 * @作者    yw
	 * @創建時間 2020年5月22日 下午12:56:59
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value={"app/wxpay"}, method={RequestMethod.POST})
    public ResponseMsg wxpay(HttpServletRequest request, Order order) throws Exception {
        return new ResponseMsg(weixinService.doUnifiedOrder(order));
    }
	
	/**
	 * 
	 * @方法名稱 wxPayNotify
	 * @功能描述 <pre>給微信回調的接口</pre>
	 * @作者    yw
	 * @創建時間 2020年5月22日 下午4:04:55
	 * @param request
	 * @return
	 */
    @PostMapping("order/wxnotify")
    @ApiOperation("微信回調")
    public String wxPayNotify(HttpServletRequest request) {
        String resXml = "";
        try {
            InputStream inputStream = request.getInputStream();
            //將InputStream轉換成xmlString
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
            } catch (IOException e) {
            	log.info(e.getMessage());
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            resXml = sb.toString();
            String result = weixinService.payBack(resXml);
            return result;
        } catch (Exception e) {
            log.info("微信手機支付失敗:" + e.getMessage());
            String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[報文爲空]]></return_msg>" + "</xml> ";
            return result;
        }
    }
}

四、測試:

安卓端發起請求,並請求支付成功:

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