微信小程序,调用建行支付。

由于微信支付费率是千分之六,在得知道建行龙支付可以做到千分之二,公司在成本这块就果断采取接建行,废话不说了直接贴代码

Service 层 

相关的参数要求还得细对建行的文档

@Service
public class CCBPayServiceImpl implements CCBPayApi {
    private static final Logger LOGGER = LoggerFactory.getLogger(CCBPayServiceImpl.class);

    @Override
    public PayResult cCBPayment(PayRequestInfo payRequestInfo) throws BizException {
        BigDecimal orderPrice = TypeConversionUtil.getBigDecimal(payRequestInfo.getOrderPrice());
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("MERCHANTID", CCBConstants.MERCHANTID);
        map.put("POSID", CCBConstants.POSID);
        map.put("BRANCHID", CCBConstants.BRANCHID);
        map.put("ORDERID", payRequestInfo.getOrderNo());
        map.put("PAYMENT", orderPrice.toString());
        map.put("CURCODE", CCBConstants.CURCODE);
        map.put("REMARK1", CCBConstants.REMARK1);
        map.put("REMARK2", CCBConstants.REMARK2);
        map.put("TXCODE", CCBConstants.TXCODE);
        map.put("TYPE", CCBConstants.TYPE);
        map.put("GATEWAY", CCBConstants.GATEWAY);
        map.put("CLIENTIP", payRequestInfo.getSpbillCreateIp());
        map.put("REGINFO", CCBConstants.REGINFO);
        map.put("PROINFO", CCBConstants.PROINFO);
        map.put("REFERER", CCBConstants.REFERER);
        // map.put("TIMEOUT", null);
        map.put("TRADE_TYPE", payRequestInfo.getTradeType());
        map.put("SUB_APPID", payRequestInfo.getAppId());
        map.put("SUB_OPENID", payRequestInfo.getOpenId());
        // MD5加密
        StringBuilder sb = new StringBuilder();
        sb.append("MERCHANTID=").append(CCBConstants.MERCHANTID).append("&POSID=").append(CCBConstants.POSID)
                .append("&BRANCHID=").append(CCBConstants.BRANCHID).append("&ORDERID=")
                .append(payRequestInfo.getOrderNo()).append("&PAYMENT=").append(orderPrice.toString())
                .append("&CURCODE=").append(CCBConstants.CURCODE).append("&TXCODE=").append(CCBConstants.TXCODE)
                .append("&REMARK1=").append(CCBConstants.REMARK1).append("&REMARK2=").append(CCBConstants.REMARK2)
                .append("&TYPE=").append(CCBConstants.TYPE).append("&PUB=").append(CCBConstants.PUB).append("&GATEWAY=")
                .append(CCBConstants.GATEWAY).append("&CLIENTIP=").append(payRequestInfo.getSpbillCreateIp())
                .append("&REGINFO=").append(CCBConstants.REGINFO).append("&PROINFO=").append(CCBConstants.PROINFO)
                .append("&REFERER=").append(CCBConstants.REFERER).append("&TRADE_TYPE=")
                .append(payRequestInfo.getTradeType()).append("&SUB_APPID=").append(payRequestInfo.getAppId())
                .append("&SUB_OPENID=").append(payRequestInfo.getOpenId());
        String sign = MD5Utils.MD5Encode(sb.toString(), "UTF-8").toLowerCase();
        map.put("MAC", sign);
        String data = null;
        CCBPayResult cCBPayResult = null;
        try {
            data = HttpClientUtil.doPost(CCBConstants.CCB_CREATE_ORDER_URL, map);
            JSONObject parseObject = JSON.parseObject(data);
            LOGGER.info("cCBPayment data  [{}]", data);
            cCBPayResult = createOrderUrl(parseObject.getString("PAYURL"));
            if (!"true".equals(cCBPayResult.getSuccess()) || !"000000".equals(cCBPayResult.getErrcode())) {
                throw new BizException(ErrorCode.BIZ_EXCEPTION.getErrcode(), "抱歉调用建行支付接口失败");
            }
        } catch (Exception e) {
            LOGGER.info("cCBPayment Error [{}],{}", data, e);
            throw new BizException(ErrorCode.BIZ_EXCEPTION.getErrcode(), e.getMessage());
        }
        return cCBPayResult;
    }

    public CCBPayResult createOrderUrl(String payUrl) {
        CCBPayResult ccbPayResult = new CCBPayResult();
        String data = null;
        try {
            data = HttpClientUtil.doPost(payUrl, null);
            JSONObject parseObject = JSON.parseObject(data);
            ccbPayResult.setSuccess(parseObject.getString("SUCCESS"));
            ccbPayResult.setErrcode(parseObject.getString("ERRCODE"));
            ccbPayResult.setErrmsg(parseObject.getString("ERRMSG"));
            ccbPayResult.setTxcode(parseObject.getString("TXCODE"));
            ccbPayResult.setAppId(parseObject.getString("appId"));
            ccbPayResult.setTimeStamp(parseObject.getString("timeStamp"));
            ccbPayResult.setNonceStr(parseObject.getString("nonceStr"));
            ccbPayResult.setPackageValue(parseObject.getString("package"));
            ccbPayResult.setSignType(parseObject.getString("signType"));
            ccbPayResult.setPaySign(parseObject.getString("paySign"));
            ccbPayResult.setPartnerid(parseObject.getString("partnerid"));
            ccbPayResult.setPrepayid(parseObject.getString("prepayid"));
            ccbPayResult.setMwebUrl(parseObject.getString("mweb_url"));
            LOGGER.info("createOrderUrl data [{}]", data);
        } catch (Exception e) {
            LOGGER.info("createOrderUrl Error [{}],{}", data, e);
            e.printStackTrace();
        }
        return ccbPayResult;
    }

    

}

封装请求的基本参数PayRequestInfo

public class PayRequestInfo implements java.io.Serializable {
    private static final long serialVersionUID = -1249414762571339701L;
    /**
     * 订单号
     */
    private String orderNo;
    /**
     * 商品描述
     */
    private String body;
    /**
     * 支付类型 1:为原生态微信支付渠道 2:建议支付渠道
     */
    private Integer payType;
    /**
     * 支付金额,单位统一为分
     */
    private Integer orderPrice;
    /**
     * 公众号/小程序 用户唯一标识openId
     */
    private String openId;
    /**
     * ip
     */
    private String spbillCreateIp;
    /**
     * 微信支付时回调地址
     */
    private String notifyUrl;
    /**
     * 公众号/小程序的appid
     */
    private String appId;
    /**
     * 交易类型
     */
    private String tradeType;
    public String getOrderNo() {
        return orderNo;
    }
    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }
    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
    public Integer getPayType() {
        return payType;
    }
    public void setPayType(Integer payType) {
        this.payType = payType;
    }
    public Integer getOrderPrice() {
        return orderPrice;
    }
    public void setOrderPrice(Integer orderPrice) {
        this.orderPrice = orderPrice;
    }
    public String getOpenId() {
        return openId;
    }
    public void setOpenId(String openId) {
        this.openId = openId;
    }
    public String getSpbillCreateIp() {
        return spbillCreateIp;
    }
    public void setSpbillCreateIp(String spbillCreateIp) {
        this.spbillCreateIp = spbillCreateIp;
    }
    public String getNotifyUrl() {
        return notifyUrl;
    }
    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }
    public String getTradeType() {
        return tradeType;
    }
    public void setTradeType(String tradeType) {
        this.tradeType = tradeType;
    }
    public String getAppId() {
        return appId;
    }
    public void setAppId(String appId) {
        this.appId = appId;
    }
}

请求建行支付结构返回的结果集

public class CCBPayResult extends PayResult implements Serializable{
    private static final long serialVersionUID = 8387757441935173456L;
    /**
     * 返回状态码 
     */
    private String success;
    /**
     * 错误码 
     * 000000 表示交易成功,非 000000 表示交易失败
     */
    private String errcode;
    /**
     * 错误信
     */
    private String errmsg;
    /**
     * 交易码 
     */
    private String txcode;
    /**
     * 微信分配的 APPID 
     */
    private String appId;
    /**
     * 时间戳 
     */
    private String timeStamp;
    /**
     * 随机串 
     */
    private String nonceStr;
    /**
     * 数据包
     */
    private String packageValue;
    /**
     * 签名方式 
     */
    private String signType;
    /**
     * 签名数据 
     */
    private String paySign;
    /**
     * 子商户的商户号 
     */
    private String partnerid;
    /**
     * 预支付交易会话 ID 
     */
    private String prepayid;
    /**
     * 微信H5支付中间页面 URL 
     */
    private String mwebUrl;
    public String getSuccess() {
        return success;
    }
    public void setSuccess(String success) {
        this.success = success;
    }
    public String getErrcode() {
        return errcode;
    }
    public void setErrcode(String errcode) {
        this.errcode = errcode;
    }
    public String getErrmsg() {
        return errmsg;
    }
    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }
    public String getTxcode() {
        return txcode;
    }
    public void setTxcode(String txcode) {
        this.txcode = txcode;
    }
    public String getAppId() {
        return appId;
    }
    public void setAppId(String appId) {
        this.appId = appId;
    }
    public String getTimeStamp() {
        return timeStamp;
    }
    public void setTimeStamp(String timeStamp) {
        this.timeStamp = timeStamp;
    }
    public String getNonceStr() {
        return nonceStr;
    }
    public void setNonceStr(String nonceStr) {
        this.nonceStr = nonceStr;
    }
    public String getPackageValue() {
        return packageValue;
    }
    public void setPackageValue(String packageValue) {
        this.packageValue = packageValue;
    }
    public String getSignType() {
        return signType;
    }
    public void setSignType(String signType) {
        this.signType = signType;
    }
    public String getPaySign() {
        return paySign;
    }
    public void setPaySign(String paySign) {
        this.paySign = paySign;
    }
    public String getPartnerid() {
        return partnerid;
    }
    public void setPartnerid(String partnerid) {
        this.partnerid = partnerid;
    }
    public String getPrepayid() {
        return prepayid;
    }
    public void setPrepayid(String prepayid) {
        this.prepayid = prepayid;
    }
    public String getMwebUrl() {
        return mwebUrl;
    }
    public void setMwebUrl(String mwebUrl) {
        this.mwebUrl = mwebUrl;
    }
    
}

HttpClientUtil

public class HttpClientUtil {
    private static HttpClient httpClient = new DefaultHttpClient();

    /**
     * 发送 get 请求
     * 
     * @param url
     * @return
     */
    public static String get(String url) {
        String body = null;
        try {
            // get 请求
            HttpGet httpGet = new HttpGet(url);
            // 发送请求
            HttpResponse httpresponse = httpClient.execute(httpGet);
            // 获取返回数据
            HttpEntity entity = httpresponse.getEntity();
            body = EntityUtils.toString(entity, "UTF-8");
            if (entity != null) {
                entity.consumeContent();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }

    /**
     * 发送get 请求
     * 
     * @param url
     * @param params
     * @return
     */
    public static String get(String url, List<NameValuePair> params) {
        String body = null;
        try {
            HttpGet httpGet = new HttpGet(url);
            String data = EntityUtils.toString(new UrlEncodedFormEntity(params));
            httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + data));
            HttpResponse httpResponse = httpClient.execute(httpGet);
            HttpEntity entity = httpResponse.getEntity();
            body = EntityUtils.toString(entity, "UTF-8");
            if (entity != null) {
                entity.consumeContent();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }

    /**
     * post
     * 
     * @param url
     * @param params
     * @return
     */
    public static String post(String url, List<NameValuePair> params) {
        String body = null;
        try {
            if (httpClient == null) {
                httpClient = new DefaultHttpClient();
            }
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity entity = httpResponse.getEntity();
            body = EntityUtils.toString(entity, "UTF-8");
            if (entity != null) {
                entity.consumeContent();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }

    /**
     * 以 closeableHttpClient方式 发送get 请求
     * 
     * @param uri
     * @return
     */
    public static String getCloseableHttpResponse(String url) {
        String body = null;
        try {
            CloseableHttpClient client = HttpClients.custom().build();
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse chr = client.execute(httpGet);
            String data = EntityUtils.toString(chr.getEntity(), "UTF-8");
            JSONObject json = JSON.parseObject(data);
            body = json.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }

    /**
     * post 请求
     * @param url
     * @param param
     * @return
     */
    public static String doPost(String url, Map<String, String> param) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            HttpPost httpPost = new HttpPost(url);
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
                httpPost.setEntity(entity);
            }
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }
}

MD5Utils

public class MD5Utils {

    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }
    
    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
        "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}

 

之前忘记没贴上Controller 层 现在加上


@Autowired
private PayApi payApi;


/**
* 统一添加订单 * * @param paymentOrder * @return */ @WeiXinLogin @RequestMapping("/addOrder") public ResponseModel addOrder(OrderVO orderVO) { LoginUserVO user = RequestContext.getContext().getUser(); String key = PAYMENT_ORDER_ADD_LOCK_KEY + user.getMemberId(); try { orderVO.setMemberId(user.getMemberId()); orderVO.setOrderNo(wechatOrderNo.nextId() + ""); orderVO.setPayType(PayType.CCBPAY);// 订单支付渠道为建行 if (redisLockUtil.tryLock(key, 10)) { Integer orderId = orderApi.addOrder(orderVO); return new ResponseModel(orderId); } else { return new ResponseModel(ErrorCode.BIZ_EXCEPTION.getErrcode(), "操作过于频繁", null); } } catch (BizException e) { LOGGER.error("addOrder error,{}", e); return new ResponseModel(e.getErrcode(), e.getErrm(), null); } finally { redisLockUtil.unlock(key); } } /** * 支付 * @param orderId * @param request * @return * @throws Exception */ @WeiXinLogin @RequestMapping("/prePay") public ResponseModel prePay(Integer orderId, HttpServletRequest request) throws Exception { String key = PAYMENT_ORDER_PREPAY_LOCK_KEY + orderId; try { LoginUserVO user = RequestContext.getContext().getUser(); PaymentOrderRecord orderRecord = orderApi.getOrderById(orderId); PayRequestInfo payRequestInfo = new PayRequestInfo(); payRequestInfo.setBody("xxx缴费"); payRequestInfo.setNotifyUrl(systemConfig.getPayNotifyUrl());//该回调地址只是微信支付,与建行支付没关系 如果是建行支付直接忽略这行代码 payRequestInfo.setOpenId(user.getAppOpenId()); payRequestInfo.setOrderNo(orderRecord.getOrderNo()); payRequestInfo.setOrderPrice(orderRecord.getOrderPrice()); payRequestInfo.setPayType(orderRecord.getPayType()); payRequestInfo.setSpbillCreateIp(getIpAddr(request)); payRequestInfo.setTradeType("MINIPRO"); payRequestInfo.setAppId(systemConfig.getAppletsAppId()); String randomNum = System.currentTimeMillis() + new Random().nextInt(10000) + ""; if (redisLockUtil.tryLock(key, randomNum, 5)) { PayResult payResult = payApi.pay(payRequestInfo); return new ResponseModel(payResult); } else { return new ResponseModel(ErrorCode.BIZ_EXCEPTION.getErrcode(), "操作过于频繁", null); } } catch (BizException e) { LOGGER.error("prePay error,{}", e); return new ResponseModel(e.getErrcode(), e.getErrm(), null); } finally { redisLockUtil.unlock(key); } } /** * 建行支付结果通知 * * @param request * @return */ @RequestMapping("/callBackCCB") public String callBackCCB(HttpServletRequest request) { LOGGER.info("callBackCCB start!"); try { Map<String, String> map = new HashMap<String, String>(); Enumeration<String> parameterNames = request.getParameterNames(); StringBuilder data = new StringBuilder(); while (parameterNames.hasMoreElements()) { String name = (String) parameterNames.nextElement(); String value = request.getParameter(name); map.put(name, value); data.append(name).append("=").append(value).append("&"); } LOGGER.info("callBackCCB source data :[{}]", data.toString());// 建行返回调原数据 StringBuilder sb = new StringBuilder(); sb.append("POSID=").append(map.get("POSID")).append("&BRANCHID=").append(map.get("BRANCHID")) .append("&ORDERID=").append(map.get("ORDERID")).append("&PAYMENT=").append(map.get("PAYMENT")) .append("&CURCODE=").append(map.get("CURCODE")).append("&REMARK1=").append(map.get("REMARK1")) .append("&REMARK2=").append(map.get("REMARK2")).append("&ACC_TYPE=").append(map.get("ACC_TYPE")) .append("&SUCCESS=").append(map.get("SUCCESS")).append("&TYPE=").append(map.get("TYPE")) .append("&REFERER=").append(map.get("REFERER")).append("&CLIENTIP=").append(map.get("CLIENTIP")) .append("&ACCDATE=").append(map.get("ACCDATE")); RSASig rsaSig = new RSASig(); rsaSig.setPublicKey(CCBConstants.PUBLICKEY);// 公钥 boolean flag = rsaSig.verifySigature(map.get("SIGN"), sb.toString()); LOGGER.info("callBackCCB Check :[{}]", flag); if ("Y".equals(map.get("SUCCESS")) && flag) {//表示支付成功 CallbackResult callbackResult = new CallbackResult(); callbackResult.setReturnCode("Y"); callbackResult.setReturnMsg("Ok"); callbackResult.setOrderNo(map.get("ORDERID"));// 订单号 payApi.callBack(callbackResult); } } catch (Exception e) { LOGGER.error("callBackCCB error,{}", e); } return null; }



//PayApi 接口的实现类
package com.qft.payment.service.pay;

import java.util.Date;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.qft.payment.api.order.OrderApi;
import com.qft.payment.api.order.constant.OrderConstant;
import com.qft.payment.api.order.constant.PayType;
import com.qft.payment.api.order.model.NotesOrder;
import com.qft.payment.api.order.model.PaymentOrderRecord;
import com.qft.payment.api.pay.CCBPayApi;
import com.qft.payment.api.pay.PayApi;
import com.qft.payment.api.pay.WechatPayApi;
import com.qft.payment.api.pay.model.CallbackResult;
import com.qft.payment.api.pay.model.PayRequestInfo;
import com.qft.payment.api.pay.model.PayResult;
import com.qft.payment.api.pay.model.RefundInfo;
import com.qft.payment.api.pay.model.WechatRefundResutl;
import com.qft.payment.api.payaccount.PayAccountApi;
import com.qft.payment.common.constant.ErrorCode;
import com.qft.payment.common.exception.BizException;
import com.qft.payment.common.util.SimpleRedisLockUtil;

/**
 * 
 * @author ckj
 *
 */
@Service
public class PayServiceImpl implements PayApi {
    private static final Logger LOGGER = LoggerFactory.getLogger(PayServiceImpl.class);
    @Autowired
    private WechatPayApi wechatPayApi;

    @Autowired
    private CCBPayApi cCBPayApi;
    private static final String ORDER_CALLBACK_LOCK_KEY = "order:lock:callback";
    @Autowired
    private SimpleRedisLockUtil redisLockUtil;

    @Override
    public PayResult pay(PayRequestInfo payRequestInfo) throws BizException {
        PayResult payResult = new PayResult();
        if (payRequestInfo.getPayType() == null) {
            throw new BizException(ErrorCode.BIZ_EXCEPTION.getErrcode(), "支付类型不能为null");
        }
        try {
            if (payRequestInfo.getPayType() == PayType.WECHATPAY) {// 表示微信原生态支付渠道
                payResult = wechatPayApi.jsApiPay(payRequestInfo);
            } else if (payRequestInfo.getPayType() == PayType.CCBPAY) {// 表示建行支付渠道
                payResult = cCBPayApi.cCBPayment(payRequestInfo);
            }
            addNotesOrder(payRequestInfo);
        } catch (Exception e) {
            LOGGER.info("pay Error [{}],{}", payRequestInfo.getOrderNo(), e);
            throw new BizException(ErrorCode.BIZ_EXCEPTION.getErrcode(), e.getMessage());
        }
        return payResult;
    }
}

 

 
posted @ 2019-08-20 10:15  阿若蜜意  阅读(4356)  评论(21编辑  收藏  举报