1.整体流程:
1.1.微信支付统一下单
1.2.网页授权
公众号调用统一支付接口跟其他支付方式基本相同,差别为JSAPI支付需要openid,需通过网页授权获得,重点说下网页授权流程
2.网页授权流程
2.1.配置
登录 https://mp.weixin.qq.com/ ,公众号设置-》 功能设置-》 网页授权设置
2.2.getcode调用指向authRedirect接口,authRedirect接口指向菜单绑定页面,此处封装了统一页面鉴权的方法,通过redirectUrl实现通用页面授权,只需要配置菜单地址可以跳转任意自定义页面。
getCode
public String queryCode(String scope, String redirectUrl) {
String appId = callUriConstants.APP_ID;
OperationAccount op = basicSettingDao.getOperationAccountByAppId(appId);
Integer accountId = op.getAccountId();
OperationAccount operationAccount = basicSettingDao.getOperationAccountByAccountId(accountId);
String wxAppid = operationAccount.getWechatAppId();
String bindPath = clientUrl + "/h5/common/authRedirect";
String authPaty = String.format("%s?%s%s", bindPath, "redirectUrl=",redirectUrl);
String getAuthCodePath = WechatApi.getOAuthCodeUrl(wxAppid, authPaty, scope, StrUtil.toString(accountId));
return getAuthCodePath;
}
authRedirect通过code换取网页授权,拿openID和token
public ModelAndView authRedirect(String code, String state, String redirectUrl) {
Integer accountId = Integer.parseInt(state);
OperationAccount operationAccount = basicSettingDao.getOperationAccountByAccountId(accountId);
String appid = operationAccount.getWechatAppId();
String secret = operationAccount.getWechatSecret();
String wxSecret = AES.decrypt(secret);
String getOAuthTokenUrl = WechatApi.getOAuthTokenUrl(appid, wxSecret, code);
JSONObject jsonObject = HttpClientUtils.httpsRequest(getOAuthTokenUrl, HttpMethod.GET.toString(), null);
String accessToken = jsonObject.getString("access_token");
String openid = jsonObject.getString("openid");
ModelAndView view = new ModelAndView();
String redirect = String.format("/mobile/static/%s", redirectUrl);
String replace = redirect.replace(" ", "");
view.setViewName("redirect:"+ replace);
view.addObject("appId", appid);
view.addObject("openId", openid);
view.addObject("accessToken", accessToken);
return view;
}
JSAPI支付统一下单接口
public Map jsapiPay(TradeOrderQueryParams params) {
Map<String, String> map = orderParams2Map(params, "JSAPI");
map.put("openid", params.getOpenid());
Gson gson=new Gson();
String orderStr= gson.toJson(map);
WXPay wxPay;
try {
wxPay = queryWxPayClient(PayConstant.DEFAULT_HOME_ID);
} catch (Exception e) {
//your code
}
Map<String, String> resp;
try {
resp = wxPay.unifiedOrder(map);
} catch (Exception e) {
}
String respStr = gson.toJson(resp);
String returnCode = resp.get("return_code");
if (WXPayConstants.SUCCESS.equals(returnCode)) {
String resultCode = (String) resp.get("result_code");
if ("SUCCESS".equals(resultCode)) {
String prepay_id = resp.get("prepay_id");
Map reMap = new HashMap();
reMap.put("appId", wxPayProperties.getAppid());
reMap.put("timeStamp", String.valueOf(new Date().getTime()));
reMap.put("package", "prepay_id=" + prepay_id);
reMap.put("nonceStr", WXPayUtil.generateNonceStr());
reMap.put("signType", WXPayConstants.HMACSHA256);
String newSign = null;
try {
newSign = WXPayUtil.generateSignature(reMap, wxPayProperties.getKey(), WXPayConstants.SignType.HMACSHA256);
} catch (Exception e) {
}
reMap.put("paySign", newSign);
return reMap;
}
}
return null;
}
private Map<String, String> orderParams2Map(TradeOrderQueryParams params,String tradeType) {
String mchTradeNo = params.getOrderId();
Double cashnum = Double.parseDouble(params.getAmount());
String total_fee = BigDecimal.valueOf(cashnum).multiply(BigDecimal.valueOf(100))
.setScale(0, BigDecimal.ROUND_HALF_UP).toString();
String spbill_create_ip = params.getSpbill_create_ip();
Map<String, String> map = new HashMap<>();
map.put("body", params.getGoodsName() + ",共" + params.getAmount() + "元");
map.put("out_trade_no", mchTradeNo);
map.put("device_info", "WEB");
map.put("attach", "测试公司");
map.put("fee_type", "CNY");
map.put("total_fee", total_fee);
map.put("spbill_create_ip", spbill_create_ip);
map.put("notify_url", wxPayProperties.getNotifyUrl());
map.put("trade_type", tradeType);
map.put("sign_type", "HMAC-SHA256");
map.put("nonce_str", WXPayUtil.generateNonceStr());
return map;
}
前端调用统一下单,拿到prepare_id调用JSAPI
$.ajax({
type: "post",
url: '/pay/jsapiPay',
data: params,
success: function(data){
var result = data;
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
...data
},
function(res){
});
}
});
微信网页开发工具地址输入
https://{}/common/code/view?redirectUrl=common.html&scope=snsapi_base
或者公众号菜单绑定该地址
3.常见问题:
3.1.当前页面的URL未注册
微信商户平台,产品中心-》开发配置-》 JSAPI支付-》 支付授权目录配置
3.2.微信 错误码10003: redirect_uri与后台配置不一致错误
对应3.1
4.参考
4.1.JSAPI支付
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
4.2.网页授权
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
5.调试工具
微信开发工具,网页调试,地址栏输入
https://{}/common/code/view?redirectUrl=common.html&scope=snsapi_base