微信公众号实现支付功能(基于官方sdk实现)--备忘001

首先要明白微信支付相关的三个账号

微信公众平台

微信支付-商户平台

微信-开放平台

1:一定要认真阅读官方开发文档,不然好多坑啊

微信公众号开发文档

官方sdk-maven


            com.github.wxpay
            wxpay-sdk
            0.0.3

 开发的相关流程:

        a>:通过统一下单方法获取到预付订单信息(prepay_id-预付订单信息)

        b>:对预付订单进行二次签名返回json数据给前端准备调起支付(二次签名需要自己实现,微信不提供,可参考微信签名方法)

        c>:前端根据获取到的数据唤起支付页面进行支付

2:根据自己项目需求写相关的接口实现(从前端获取官方文档中的相关参数)

3:调官方sdk填充数据的方法进行关键信息的填充

//调官方sdk方法填充数据
data = wxPay.fillRequestData(data);
   /**
     * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign 
* 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口 * * @param reqData * @return * @throws Exception */ public Map fillRequestData(Map reqData) throws Exception { reqData.put("appid", config.getAppID()); reqData.put("mch_id", config.getMchID()); reqData.put("nonce_str", WXPayUtil.generateNonceStr()); if (SignType.MD5.equals(this.signType)) { reqData.put("sign_type", WXPayConstants.MD5); } else if (SignType.HMACSHA256.equals(this.signType)) { reqData.put("sign_type", WXPayConstants.HMACSHA256); } reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType)); return reqData; }

4:完成相关数据填充后调官方sdk的统一下单方法

//调官方sdk统一下单方法
Map result = wxPay.unifiedOrder(data);
     /**
     * 作用:统一下单
* 场景:公共号支付、扫码支付、APP支付 * @param reqData 向wxpay post的请求数据 * @return API返回数据 * @throws Exception */ public Map unifiedOrder(Map reqData) throws Exception { return this.unifiedOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); } /** * 作用:统一下单
* 场景:公共号支付、扫码支付、APP支付 * @param reqData 向wxpay post的请求数据 * @param connectTimeoutMs 连接超时时间,单位是毫秒 * @param readTimeoutMs 读超时时间,单位是毫秒 * @return API返回数据 * @throws Exception */ public Map unifiedOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { String url; if (this.useSandbox) { url = WXPayConstants.SANDBOX_UNIFIEDORDER_URL; } else { url = WXPayConstants.UNIFIEDORDER_URL; } String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); return this.processResponseXml(respXml); }

5:对统一下单方法返回数据进行二次签名准备返回给前端(注意该方法需要自己去实现,官方没有单独提供二次签名方法,我是把官方签名方法copy出来自己建了一个工具类,然后调自己的工具类进行的二次签名,仅供参考)

if (req.getTradeType().equals(PayRequest.TRADE_TYPE_JSAPI)) {
    out.put("appId", result.get("appid"));
    out.put("nonceStr", String.valueOf(System.currentTimeMillis()));
    out.put("package", "prepay_id=" + result.get("prepay_id"));
    out.put("signType", "MD5");
    out.put("timeStamp", String.valueOf(System.currentTimeMillis()/1000));
    //##对返回数据进行二次签名 TODO
    String packageSign = WXPayUtil.generateSignature(out,wxPayProperties.getKey());
    out.put("paySign", packageSign);				
} 
   /**
     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
     *
     * @param data 待签名数据
     * @param key API密钥
     * @param signType 签名方式
     * @return 签名
     */
    public static String generateSignature(final Map data, String key, SignType signType) throws Exception {
        Set keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(WXPayConstants.FIELD_SIGN)) {
                continue;
            }
            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                sb.append(k).append("=").append(data.get(k).trim()).append("&");
        }
        sb.append("key=").append(key);
        if (SignType.MD5.equals(signType)) {
            return MD5(sb.toString()).toUpperCase();
        }
        else if (SignType.HMACSHA256.equals(signType)) {
            return HMACSHA256(sb.toString(), key);
        }
        else {
            throw new Exception(String.format("Invalid sign_type: %s", signType));
        }
    }
/**
     * 生成 MD5
     *
     * @param data 待处理数据
     * @return MD5结果
     */
    public static String MD5(String data) throws Exception {
        java.security.MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString().toUpperCase();
    }

6:把签名后的数据返回给前端,剩下的事就交给前端实现

你可能感兴趣的:(微信开发相关)