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

微信公众平台 <https://mp.weixin.qq.com/>


微信支付-商户平台 <https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F>


微信-开放平台 <https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN>


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

微信公众号开发文档 <https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1>

官方sdk-maven
<dependency> <groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId> <version>0.0.3</version> </dependency>
 开发的相关流程:

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

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


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

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

3:调官方sdk填充数据的方法进行关键信息的填充
//调官方sdk方法填充数据 data = wxPay.fillRequestData(data); /** * 向 Map 中添加
appid、mch_id、nonce_str、sign_type、sign <br> * 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口 *
* @param reqData * @return * @throws Exception */ public Map<String, String>
fillRequestData(Map<String, String> 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<String, String> result = wxPay.unifiedOrder(data); /** *
作用:统一下单<br> * 场景:公共号支付、扫码支付、APP支付 * @param reqData 向wxpay post的请求数据 * @return
API返回数据 * @throws Exception */ public Map<String, String>
unifiedOrder(Map<String, String> reqData) throws Exception { return
this.unifiedOrder(reqData, config.getHttpConnectTimeoutMs(),
this.config.getHttpReadTimeoutMs()); } /** * 作用:统一下单<br> * 场景:公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据 * @param connectTimeoutMs 连接超时时间,单位是毫秒 *
@param readTimeoutMs 读超时时间,单位是毫秒 * @return API返回数据 * @throws Exception */
public Map<String, String> unifiedOrder(Map<String, String> 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<String, String> data, String key, SignType
signType) throws Exception { Set<String> 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:把签名后的数据返回给前端,剩下的事就交给前端实现