微信公众号支付开发与统一网页鉴权

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

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页