• 接入微信公众号支付


    官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

    官方的一张图
    这里写图片描述

    我们只需要开发图中红色的部分。

    1.生成图文消息链接或二维码

    网上随便找个网站就行,例如草料

    2.生成商户订单,调用统一下单API

    调用统一下单API必须传用户的openid,openid是每个用户之于每个公众号的唯一标志。以下为获取的openid的步骤。获取openid的官方文档

    a.设置网页授权回调域名

    在以下路径”开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”进行配置。

    b.构造授权链接给用户去访问

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
    各个参数的顺序不能改变
    - APPID 公众号唯一标识
    - REDIRECT_URI 授权后重定向的回调链接地址,请使用urlEncode对链接进行处理(请不要直接再此地址直接调起微信支付)。
    - SCOPE 应用授权作用域,有两种方式
    - snsapi_base 不会弹出要求用户授权页面,静默的获得code(只能获得openid)
    - snsapi_userinfo 会弹出验证页面,可以获得用户公开信息
    - STATE 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节

    如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。

    c.根据code获得access_token,openid,refresh_token等

    https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

    • APPID 公众号唯一标识
    • SECRET 公众号的唯一凭证密钥(此密钥不应给用户接触,所有此链接应在服务器发起请求
    • CODE 上一步中获得的code(注意,每个code只能用一次

    微信返回数据

    • access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
    • expires_in access_token接口调用凭证超时时间,单位(秒)
    • refresh_token 用户刷新access_token
    • openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
    • scope 用户授权的作用域,使用逗号(,)分隔

    如果只要获得用户的openid的,当这一步就已经结束了。

    d.调用统一下单API

    官方文档

    调用这个API可以自己根据文档要求构造请求,也可以直接只用微信封装好的sdk,以下介绍使用sdk的方法。

    通过maven安装sdk

    <dependency>
        <groupId>com.github.wxpay</groupId>
        <artifactId>wxpay-sdk</artifactId>
        <version>0.0.3</version>
    </dependency>
    //这个官方demo的代码,调用统一下单接口
    public static void main(String[] args) throws Exception {
            MyConfig config = new MyConfig();
            WXPay wxpay = new WXPay(config);
            Map<String, String> data = new HashMap<String, String>();
            data.put("body", "腾讯充值中心-QQ会员充值");
            data.put("out_trade_no", "2016090910595900000012");
            data.put("device_info", "");
            data.put("fee_type", "CNY");
            data.put("total_fee", "1");
            data.put("spbill_create_ip", "123.12.12.123");
            data.put("notify_url", "http://www.example.com/wxpay/notify");
            data.put("trade_type", "NATIVE");  // 此处指定为扫码支付
            data.put("product_id", "12");
    
            try {
                Map<String, String> resp = wxpay.unifiedOrder(data);
                System.out.println(resp);
            } catch (Exception e) {
                e.printStackTrace();
            }
     }
    

    把接口返回的数据取出需要的,然后进行签名,签名的Key为之前配置过的。

        Map<String, String> result = new HashMap<>(6);
        result.put("appId",config.getAppID());
        result.put("timeStamp",String.valueOf(new Date().getTime()));
        result.put("nonceStr",resp.get("nonce_str"));
        result.put("package","prepay_id="+resp.get("prepay_id"));
        result.put("signType","MD5");
        result.put("paySign",WXPayUtil.generateSignature(result,config.getKey()));  

    签完名将数据传递给需要调起支付的前端页面。

    JS调起微信支付

    注意,调起支付的页面必须是在配置的支付授权目录的路径下的,不然调起支付失败。

     if (typeof WeixinJSBridge == "undefined") {
         if (document.addEventListener) {
             document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
         } else if (document.attachEvent) {
             document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
             document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
         }
     } else {
         onBridgeReady(result);
     }
     function onBridgeReady(t) {
     //t为后台传过来的参数
         WeixinJSBridge.invoke(
             'getBrandWCPayRequest', t,
             function (res) {
                 if (res.err_msg == "get_brand_wcpay_request:ok") {
                     window.location.href="${pageContext.request.contextPath}/result.htm?msg=success"
                 }     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
            });
     }

    后台接收微信的异步回调

    官方文档

    一定要返回给微信已经收到通知的回复,一定要避免重复通知带来的业务逻辑错误。
    微信通知是xml格式的数据。所以要先读出来,然后用密钥验证一下签名。

            InputStreamReader isr=new InputStreamReader(request.getInputStream());
            BufferedReader br=new BufferedReader(isr);
            StringBuilder notifyData=new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                notifyData.append(line);
            }
             Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData.toString());  // 转换成map
            if(wxPay.isPayResultNotifySignatureValid(notifyMap)) {
                // 签名正确
                // 进行处理。
                // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
                if("SUCCESS".equals(notifyMap.get("result_code"))){
    
                }
            }else {
                // 签名错误,如果数据里没有sign字段,也认为是签名错误
    
            }

    如果要展示支付结果的时候微信的通知还没来,可以主动的进行查询

     public static void main(String[] args) throws Exception {
    
            MyConfig config = new MyConfig();
            WXPay wxpay = new WXPay(config);
    
            Map<String, String> data = new HashMap<String, String>();
            data.put("out_trade_no", "2016090910595900000012");
    
            try {
                Map<String, String> resp = wxpay.orderQuery(data);
                System.out.println(resp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
  • 相关阅读:
    .NET的JSNO 序列化跟反序列化
    SQL Server 查询分析器提供的所有键盘快捷方式(转)
    SQL Server 中WITH (NOLOCK)浅析(转潇湘隐者)
    Microsoft Dynamics CRM 2011的组织服务中的RetrieveMultiple方法(转)
    C#对多个集合和数组的操作(合并,去重,判断)
    Silverlight Telerik控件学习:主题Theme切换html教程
    VMware 11安装Mac OS X 10.10
    Android 下载网络图片注意的问题
    对下载文件是否完整的判断方法
    Android实现通用的ActivityGroup(效果类似Android微博客户端主界面),强烈建议不要再使用TabActivity
  • 原文地址:https://www.cnblogs.com/A-yes/p/9894156.html
Copyright © 2020-2023  润新知