1. 程式人生 > >微信支付介面開發_支付寶介面開發_銀行支付通道_企業對私低費率

微信支付介面開發_支付寶介面開發_銀行支付通道_企業對私低費率

1.準備工作

首先登入微信公眾平臺,獲取並配置以下微信開發配置:

  • 開發者ID【AppID和AppSecret】
  • 伺服器配置
    1.url伺服器地址設定
    2.Token【自己設定,必須英文或數字】
    3.EncodingAESKey[自己隨機生成,用於訊息加解密]

然後登入微信商戶平臺,獲取並配置以下微信支付配置:

  • 商戶號(mchId)
  • API祕鑰(key)
  • API證書(java版主要使用:apiclient_cert.p12)

 PS:需要微信公眾號支付銀行對私介面,請聯絡電話/微信17605918869

2.程式碼展示

提醒:此處粘貼出的程式碼為方便初學者比較直觀的瞭解、學習微信公眾號支付,部分程式碼並未按照編碼規範封裝成方法、工具類

將微信支付所有引數定義為 WeChatConfig.java

public classWeChatConfig{
    /**公眾號AppId*/
    public static final APP_ID = "";    

    /**公眾號AppSecret*/
    public static final APP_SECRET = "";

    /**微信支付商戶號*/
    public static final String MCH_ID = "";

    /**微信支付API祕鑰*/
    public static final String KEY = "";

    /**微信支付api證書路徑*/
public static final String CERT_PATH = "***/apiclient_cert.p12"; /**微信統一下單url*/ public static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; /**微信申請退款url*/ public static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund"; /**微信支付通知url*/
public static final String NOTIFY_URL = "此處url用於接收微信伺服器傳送的支付通知,並處理商家的業務"; /**微信交易型別:公眾號支付*/ public static final String TRADE_TYPE_JSAPI = "JSAPI"; /**微信交易型別:原生掃碼支付*/ public static final String TRADE_TYPE_NATIVE = "NATIVE"; /**微信甲乙型別:APP支付*/ public static final String TRADE_TYPE_APP = "APP"; }

處理微信公眾號支付請求的Controller:WeChatOrderController.java

@RequestMapping(value="/m/weChat/")
@Controller("weChatOrderController")
public classWeChatOrderController{

    @Autowired
    private OrderService orderService;
    @Autowired
    private WechatPayService wechatPayService;
    @Autowired
    private NotifyReturnService notifyReturnService;

    @RequestMapping(value = "unifiedOrder")
    public String unifiedOrder(HttpServletRequest request,Model model){
        //使用者同意授權,獲得的code
        String code = request.getParameter("code");
        //請求授權攜帶的引數【根據自己需要設定值,此處我傳的是訂單id】
        String state = request.getParameter("state");
        Order order = orderService.get(state);//訂單資訊
        //通過code獲取網頁授權access_token
        AuthToken authToken = WeChatUtils.getTokenByAuthCode(code);
        //構建微信統一下單需要的引數
        Map<String,Object> map = Maps.newHashMap();
        map.put("openId",authToken.getOpenid());//使用者標識openId
        map.put("remoteIp",request.getRemoteAddr());//請求Ip地址
        //呼叫統一下單service
        Map<String,Object> resultMap = WeChatPayService.unifiedOrder(order,map);
        String returnCode = (String) resultMap.get("return_code");//通訊標識
        String resultCode = (String) resultMap.get("result_code");//交易標識
        //只有當returnCode與resultCode均返回“success”,才代表微信支付統一下單成功
        if (WeChatConstant.RETURN_SUCCESS.equals(resultCode)&&WeChatConstant.RETURN_SUCCESS.equals(returnCode)){
            String appId = (String) resultMap.get("appid");//微信公眾號AppId
            String timeStamp = WeChatUtils.getTimeStamp();//當前時間戳
            String prepayId = "prepay_id="+resultMap.get("prepay_id");//統一下單返回的預支付id
            String nonceStr = WeChatUtils.getRandomStr(20);//不長於32位的隨機字串
            SortedMap<String,Object> signMap = Maps.newTreeMap();//自然升序map
            signMap.put("appId",appId);
            signMap.put("package",prepayId);
            signMap.put("timeStamp",timeStamp);
            signMap.put("nonceStr",nonceStr);
            signMap.put("signType","MD5");
            model.addAttribute("appId",appId);
            model.addAttribute("timeStamp",timeStamp);
            model.addAttribute("nonceStr",nonceStr);
            model.addAttribute("prepayId",prepayId);
            model.addAttribute("paySign",WeChatUtils.getSign(signMap));//獲取簽名
        }else {
            logger.error("微信統一下單失敗,訂單編號:"+order.getOrderNumber()+",失敗原因:"+resultMap.get("err_code_des"));
            return "redirect:/m/orderList";//支付下單失敗,重定向至訂單列表
        }
        //將支付需要引數返回至頁面,採用h5方式呼叫支付介面
        return "/mobile/order/h5Pay";
    }
}

微信支付前端發起頁面: weChatPayTest.jsp

  • 支付按鈕href中的redirect_uri= http://自己服務的ip或者域名/m/weChat/unifiedOrder 強調部分需要進行uriEncode
  • 此處程式碼為在微信公眾號內網頁呼叫,故使用的是微信網頁授權方式,將訂單id通過支付介面中state引數進行傳遞
<!DOCTYPE HTML><%@pagecontentType="text/html;charset=UTF-8"language="java" %><html><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1,user-scalable=0"><metaname="screen-orientation"content="portrait"><metaname="x5-orientation"content="portrait"><linkrel="stylesheet"href="/static/weui/dist/style/weui.min.css"><title>微信公眾號支付測試</title></head><body><divclass="container"id="container"><ahref="https://open.weixin.qq.com/connect/oauth2/authorizeappid=wx67e9c91f0bac335d&redirect_uri=http%3a%2f%2f***%2fm%2fweChat%2funifiedOrder&response_type=code&scope=snsapi_base&state=${order.id}#wechat_redirect"class="weui_btn weui_btn_primary">立即支付</a></div></body></html>

h5方式呼叫微信支付介面:h5Pay.jsp

  • WeixinJSBridge為微信公眾號內建物件,所以必須在公眾號內部網頁使用
<%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><title>確認支付</title><scripttype="text/javascript"src="/static/jquery/jquery-1.11.3.min.js"></script><scripttype="text/javascript"src="/static/jquery-plugin/jquery.form.js"></script></head><body><inputtype="hidden"name="appId"value="${appId}"><inputtype="hidden"name="nonceStr"value="${nonceStr}"><inputtype="hidden"name="prepayId"value="${prepayId}"><inputtype="hidden"name="paySign"value="${paySign}"><inputtype="hidden"name="timeStamp"value="${timeStamp}"></body><script>functiononBridgeReady(){
        var appId = $("input[name='appId']").val();
        var nonceStr = $("input[name='nonceStr']").val();
        var prepayId = $("input[name='prepayId']").val();
        var paySign = $("input[name='paySign']").val();
        var timeStamp = $("input[name='timeStamp']").val();
        WeixinJSBridge.invoke(
                'getBrandWCPayRequest', {
                    "appId":appId,
                    "timeStamp":timeStamp,
                    "nonceStr":nonceStr,
                    "package":prepayId,
                    "signType":"MD5",
                    "paySign":paySign
                },
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                    location.href="支付成功返回商家自定義頁面";
                }else {//這裡支付失敗和支付取消統一處理
                    alert("支付取消");
                    location.href="支付失敗返回商家自定義頁面";
                }
            }
        );
    }

    $(document).ready(function () {
        if (typeof WeixinJSBridge == "undefined"){
            if (document.addEventListener){
                document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
            }elseif (document.attachEvent){
                document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
            }
        }else {
            onBridgeReady();
        }
    });
</script></html>

微信支付訂單Service:WeChatPayService.java

/**
*微信支付統一下單
**/
public Map<String,Object> unifiedOrder(Order order, Map<String,Object> map){
    Map<String,Object> resultMap;
    try {
            WxPaySendData paySendData = new WxPaySendData();
            //構建微信支付請求引數集合
            paySendData.setAppId(WeChatConstant.APP_ID);
            paySendData.setAttach("微信訂單支付:"+order.getOrderNumber());
            paySendData.setBody("商品描述");
            paySendData.setMchId(WeChatConfig.MCH_ID);
            paySendData.setNonceStr(WeChatUtils.getRandomStr(32));
            paySendData.setNotifyUrl(WeChatConfig.NOTIFY_URL);
            paySendData.setDeviceInfo("WEB");
            paySendData.setOutTradeNo(order.getOrderNumber());
            paySendData.setTotalFee(order.getSumFee());
            paySendData.setTradeType(WeChatConfig.TRADE_TYPE_JSAPI);
            paySendData.setSpBillCreateIp((String) map.get("remoteIp"));
            paySendData.setOpenId((String) map.get("openId"));
            //將引數拼成map,生產簽名
            SortedMap<String,Object> params = buildParamMap(paySendData);
            paySendData.setSign(WeChatUtils.getSign(params));
            //將請求引數物件轉換成xml
            String reqXml = WeChatUtils.sendDataToXml(paySendData);
            //傳送請求
            byte[] xmlData = reqXml.getBytes();
            URL url = new URL(WeChatConfig.UNIFIED_ORDER_URL);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.setRequestProperty("Content_Type","text/xml");
            urlConnection.setRequestProperty("Content-length",String.valueOf(xmlData.length));
            DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());
            outputStream.write(xmlData);
            outputStream.flush();
            outputStream.close();
            resultMap = WeChatUtils.parseXml(urlConnection.getInputStream());
        } catch (Exception e) {
            throw new ServiceException("微信支付統一下單異常",e);
        }
        return resultMap;

    /**
     * 構建統一下單引數map 用於生成簽名
     * @param data
     * @return SortedMap<String,Object>
     */
    private SortedMap<String,Object> buildParamMap(WxPaySendData data) {
        SortedMap<String,Object> paramters = newTreeMap<String, Object>();
        if (null != data){
            if (StringUtils.isNotEmpty(data.getAppId())){
                paramters.put("appid",data.getAppId());
            }
            if (StringUtils.isNotEmpty(data.getAttach())){
                paramters.put("attach",data.getAttach());
            }
            if (StringUtils.isNotEmpty(data.getBody())){
                paramters.put("body",data.getBody());
            }
            if (StringUtils.isNotEmpty(data.getDetail())){
                paramters.put("detail",data.getDetail());
            }
            if (StringUtils.isNotEmpty(data.getDeviceInfo())){
                paramters.put("device_info",data.getDeviceInfo());
            }
            if (StringUtils.isNotEmpty(data.getFeeType())){
                paramters.put("fee_type",data.getFeeType());
            }
            if (StringUtils.isNotEmpty(data.getGoodsTag())){
                paramters.put("goods_tag",data.getGoodsTag());
            }
            if (StringUtils.isNotEmpty(data.getLimitPay())){
                paramters.put("limit_pay",data.getLimitPay());
            }
            if (StringUtils.isNotEmpty(data.getMchId())){
                paramters.put("mch_id",data.getMchId());
            }
            if (StringUtils.isNotEmpty(data.getNonceStr())){
                paramters.put("nonce_str",data.getNonceStr());
            }
            if (StringUtils.isNotEmpty(data.getNotifyUrl())){
                paramters.put("notify_url",data.getNotifyUrl());
            }
            if (StringUtils.isNotEmpty(data.getOpenId())){
                paramters.put("openid",data.getOpenId());
            }
            if (StringUtils.isNotEmpty(data.getOutTradeNo())){
                paramters.put("out_trade_no",data.getOutTradeNo());
            }
            if (StringUtils.isNotEmpty(data.getSign())){
                paramters.put("sign",data.getSign());
            }
            if (StringUtils.isNotEmpty(data.getSpBillCreateIp())){
                paramters.put("spbill_create_ip",data.