1. 程式人生 > >【原創】微信小程序支付(普通模式,公眾號支付同適用)java後臺案例

【原創】微信小程序支付(普通模式,公眾號支付同適用)java後臺案例

退款 back ram 點擊 後臺 exceptio ppk rap 關聯

微信小程序支付官方接口文檔:點擊查看微信開放平臺api開發文檔

涉及的數據庫表結構在最後面貼上

1.1 小程序支付說明

技術分享圖片

1.2 小程序輕量級支付模板(引用碼雲作者egan)引入jar包

       <dependency>
            <groupId>com.egzosn</groupId>
            <artifactId>pay-java-common</artifactId>
            <version>2.12.1</version>
        </dependency
> <dependency> <groupId>com.egzosn</groupId> <artifactId>pay-java-wx</artifactId> <version>2.12.1</version> </dependency>

1.3 初始化微信支付配置存儲類



private WxPayService wxUserPayService;
/**
     * 微信支付必要信息初始化
     * 
@param appId */
private void wxUserPayServiceInit(String appId) { if (wxUserPayService == null) { WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage(); wxPayConfigStorage.setMchId(mchId);//支付商戶號 wxPayConfigStorage.setAppid(appId);//小程序appid
// wxPayConfigStorage.setKeyPublic("轉賬公鑰,轉賬時必填"); wxPayConfigStorage.setSecretKey(appKey);// 商戶支付密鑰 wxPayConfigStorage.setNotifyUrl(domain + "/wx/userpaycallback");//支付結果回調接口地址,必須外網可訪問的完整url地址 wxPayConfigStorage.setSignType("MD5"); wxPayConfigStorage.setInputCharset("utf-8"); // https證書設置,退款必須 方式一 /*HttpConfigStorage httpConfigStorage = new HttpConfigStorage(); httpConfigStorage.setKeystorePath(keystorePath);//apiclient_cert.p12證書存放路徑,填寫絕對路徑 httpConfigStorage.setStorePassword(mchId); httpConfigStorage.setPath(true); httpConfigStorage.setMaxTotal(20); httpConfigStorage.setDefaultMaxPerRoute(10); wxUserPayService = new WxPayService(wxPayConfigStorage, httpConfigStorage);*/ wxUserPayService = new WxPayService(wxPayConfigStorage); } }

1.4 付款前生成微信預支付交易單,返回正確的預支付交易參數信息,供給微信小程序前端開發者調用付款API

       String title =  "開通會員";//支付下單標題
            double total_fee = vipConfigInfoService.getInfo().getPrice();//實際支付金額
            // 測試默認都是
//            if (settingActive.equals("test")) {
//                total_fee = 0.01;
//            }
            
            // 添加支付記錄信息,生成商戶訂單號,這裏用支付記錄id
            String out_trade_no = payService.representVip(type, appId, openId, userId, total_fee, title);
            
            wxUserPayServiceInit(appId);//初始化微信支付配置存儲類
            PayOrder order = new PayOrder(title, type, new BigDecimal(total_fee), out_trade_no);
            order.setTransactionType(WxTransactionType.JSAPI);
            order.setOpenid(openId);
            order.setSpbillCreateIp(spbill_create_ip);//終端ip,調用微信支付API的機器IP
            order.setAddition(type);
            JSONObject result = wxUserPayService.unifiedOrder(order);//微信統一下單接口,此方法在引入的jar中,直接傳入必填的信息調用即可
            System.out.println("請求微信支付統一下單結果:" + result.toString());
            String timeStamp = System.currentTimeMillis() / 1000 + "";
            JSONObject json = new JSONObject();
            json.put("nonceStr", result.getString("nonce_str"));
            json.put("package", "prepay_id=" + result.getString("prepay_id"));
            json.put("timeStamp", timeStamp);
            String stringSignTemp = "appId=" + appId + "&nonceStr=" + result.getString("nonce_str")
                    + "&package=prepay_id=" + result.getString("prepay_id") + "&signType=MD5&timeStamp="
                    + timeStamp;
            json.put("paySign", wxUserPayService.createSign(stringSignTemp, "utf-8"));

            return json;//接口方法返回預支付交易信息,小程序前端獲取返回參數,調用對應的付款接口

1.5 支付回調(付款後微信服務器後臺回調支付結果信息)

/**
     * 
     * 支付回調接口
     */
    @RequestMapping("/userpaycallback")
    public String wxUserPaycallback(HttpServletRequest request) {
        try {

            Map<String, Object> params = wxUserPayService.getParameter2Map(request.getParameterMap(),
                    request.getInputStream());
            if (null == params) {
                throw new Exception("回調參數為空");
            }
            // 校驗
            if (!wxUserPayService.verify(params)) {
                throw new Exception("校驗失敗");
            }
            payDone(params);//支付處理
            return wxUserPayService.getPayOutMessage("SUCCESS", "成功").toMessage();

        } catch (Exception e) {
            e.printStackTrace();
            return wxUserPayService.getPayOutMessage("FALL", "失敗").toMessage();
        }
    }


   /**
     * 支付結果處理
     */
    private void payDone(Map<String, Object> dataMap) throws Exception {
        System.out.println("支付回調:" + JSON.toJSONString(dataMap));
        // {"transaction_id":"4200000109201805293331420304","nonce_str":"402880e963a9764b0163a979a16e0002","bank_type":"CFT","openid":"oXI6G5Jc4D44y2wixgxE3OPwpDVg","sign":"262978D36A3093ACBE4B55707D6EA7B2","fee_type":"CNY","mch_id":"1491307962","cash_fee":"10","out_trade_no":"14913079622018052909183048768217","appid":"wxa177427bc0e60aab","total_fee":"10","trade_type":"JSAPI","result_code":"SUCCESS","time_end":"20180529091834","is_subscribe":"N","return_code":"SUCCESS"}
        String result_code = dataMap.get("result_code").toString();//支付結果code
        String out_trade_no = dataMap.get("out_trade_no").toString();//商戶交易訂單id,此為支付記錄id

        if (!result_code.equals("SUCCESS")) {
            throw new Exception("支付回調失敗:" + JSON.toJSONString(dataMap));
        }
        Pay pay = payService.getById(out_trade_no);//獲取支付記錄
        if (pay == null || pay.getStatus() != 10) {//10=可用/待支付 20=支付成功 30=支付失敗
            throw new Exception("支付記錄已經處理");
        }
        payService.pay(out_trade_no, result_code.equals("SUCCESS") ? 20 : 30);//根據回調結果更改支付結果狀態
        // 升級成會員的數據處理
        if(result_code.equals("SUCCESS")) {//支付結果SUCCESS,支付成功開通會員,進行下一步操作
            Document doc=new Document();
            doc.put("vipStatus", 20);//狀態20開通會員
            doc.put("vipCreateTime", new Date());
            doc.put("expireTime", StringUtil.getMonthNextOrBeforeDate(3));//設置過期時間為3個月後
            userService.updateUserVip(pay.getUserId(),doc);
        }
        
    }

2.1數據庫表

支付記錄表Pay

字段

名稱

類型

備註

_id 唯一標識 String
type 支付訂單類型 String
orderId 關聯訂單Id String
remark 備註 String
openId 微信用戶openId String
account 金額 double
status 狀態 int 10=可用/待支付 20=支付成功 30=支付失敗
createTime 創建時間 Date
callBackTime 回調時間 Date


3.1需要引用的類class

import com.egzosn.pay.common.bean.PayOrder;
import com.egzosn.pay.common.util.XML;
import com.egzosn.pay.wx.api.WxPayConfigStorage;
import com.egzosn.pay.wx.api.WxPayService;
import com.egzosn.pay.wx.bean.WxTransactionType;

結尾:此示例是用戶開通vip的接口方法,重要的代碼都有貼上。有疑問歡迎各位留言或聯系郵箱[email protected],請多多指教

【原創】微信小程序支付(普通模式,公眾號支付同適用)java後臺案例