第三方支付之微信支付(扫码支付)


第一步:注册微信支付账户,开通扫码支付

具体流程请参照官方说明

第二步:创建Maven项目

1. 添加微信支付SDK依赖、二维码工具依赖(微信支付需要自己通过二维码工具生成支付二维码)

     <!-- 微信支付 -->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>

        <!-- google二维码工具 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.1.0</version>
        </dependency>

2. 实现SDK微信配置类,创建商户自己的配置类

public class WxPayConfig implements WXPayConfig{

    private byte[] certData;

    //初始化退款、撤销时的商户证书
    public WxPayConfig() throws Exception {
        String certPath = "D://第三方开放平台/wx_apiclient_cert.p12";
        File file = new File(certPath);
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();
    }

    public String getAppID() {
        return "";
    }

    /** 微信支付商户号 */
    public String getMchID() {
        return "";
    }

    public String getKey() {
        return "";
    }

    public int getHttpConnectTimeoutMs() {
        return 8000;
    }

    public int getHttpReadTimeoutMs() {
        return 10000;
    }

    @Override
    public InputStream getCertStream() {
        ByteArrayInputStream certBis;
        certBis = new ByteArrayInputStream(this.certData);
        return certBis;
    }
}

3. 创建微信支付的控制器类

3.1 初始化微信支付的SDK客户端

private WxPayConfig config;

private WXPay wxpay;

public WxPayController() {
   try {
      //初始化微信支付客户端
      config = new WxPayConfig();
      wxpay = new WXPay(config);
   } catch (Exception e) {
      e.printStackTrace();
   }
}

 3.2 创建预支付接口,生成支付二维码(可以在页面添加img标签,让它的url指向这里就能直接在页面特定区域显示二维码了)

/**
     * 预支付接口,生成支付二维码
     * @param order
     * @return
     * @throws Exception
     */
    @RequestMapping("/wxpay/pay")
    public void pay(HttpServletResponse response) throws Exception {
        //TODO:这里执行商户系统创建新的订单操作
        WxPayOrder order = new WxPayOrder();
        order.setOut_trade_no(System.currentTimeMillis() + "");
        wxPayService.createOrder(order);

        //设置请求参数
        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "微信支付测试");
        data.put("out_trade_no", order.getOut_trade_no());
        data.put("device_info", "");
        data.put("fee_type", "CNY");
        data.put("total_fee", "1");
        data.put("spbill_create_ip", "192.168.0.119");
        data.put("notify_url", notify_url);
        data.put("trade_type", "NATIVE");  // 此处指定为扫码支付
        data.put("product_id", "12");

        try {
            //发起支付
            Map<String, String> resp = wxpay.unifiedOrder(data);
            //获取二维码URL
            String code_url = resp.get("code_url");
            //根据url生成二维码
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            // 设置二维码参数
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            BitMatrix bitMatrix = multiFormatWriter.encode(code_url, BarcodeFormat.QR_CODE, 300, 300, hints);
            //返回二维码
            MatrixToImageWriter.writeToStream(bitMatrix, "jpg", response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 3.3 创建支付结果回调接口(回调的URL必须公网可以访问,测试时可以使用花生壳等工具映射一个公网地址

/**
     * 支付结果回调
     * @return
     * @throws Exception
     */
    @PostMapping("/wxpay/notify_url")
    public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 读取回调内容
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();

        // 支付结果通知的xml格式数据
        String notifyData = sb.toString(); 

        // 转换成map
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);

        //支付确认内容
        String resXml = "";
        //验证签名
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {        // 签名正确
            WxPayOrder order = wxPayService.getOrder(notifyMap.get("out_trade_no"));
            if(order != null) {
                if("SUCCESS".equals(notifyMap.get("result_code"))) {    //交易成功
                    // TODO:更新订单
                    System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付成功");
                } else {    //交易失败
                    System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
                }
            }
            // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功

            //设置成功确认内容
            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
        }
        else {  // 签名错误,如果数据里没有sign字段,也认为是签名错误
            //设置失败确认内容
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg></return_msg>" + "</xml> ";
            System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
        }

        //发送通知
        response.getWriter().println(resXml);
    }

 3.4 创建申请退款接口(这里一定要注意先要下载并配置证书,否则会报错;证书下载请参考官方文档,证书配置见商户微信配置类)

/**
     * 微信申请退款接口
     * @param out_trade_no        订单号
     * @throws Exception
     */
    @RequestMapping("/wxpay/refund")
    public void refund(String out_trade_no) throws Exception {
        //设置请求参数
        HashMap<String, String> data = new HashMap<String, String>();
        data.put("out_trade_no", out_trade_no);
        data.put("out_refund_no", out_trade_no);
        data.put("total_fee", "1");
        data.put("refund_fee", "1");
        data.put("refund_fee_type", "CNY");
        data.put("op_user_id", config.getMchID());

        try {
            //调用sdk发起退款
            Map<String, String> result = wxpay.refund(data);
            if("SUCCESS".equals(result.get("result_code"))) {
                //TODO:更新订单
                System.out.println("订单" + out_trade_no + "微信退款成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

第三步:测试支付、退款

1. 运行项目 mvn jetty:run

2. 测试支付接口:http://localhost:8080/wxpay/pay

3. 测试退款接口:http://localhost:8080/wxpay/refund

说明:当前项目仅实现了简单的支付和退款功能,代码大部分搬自官方示例,并不包括完整的支付流程,有什么不明白的地方,欢迎留言

项目源码:https://github.com/13babybear/bounter-pay

时间: 2024-12-29 07:33:58

第三方支付之微信支付(扫码支付)的相关文章

微信支付宝扫码支付相关接口

微信支付宝扫码支付相关接口 ##################支付宝扫码支付################## 当面付--扫码支付:商户专柜或者收银台打印或者副屏展示支付宝二维码,用户使用支付宝钱包扫码工具扫描二维码,并在手机端完成付款. 文档中心:http://doc.open.alipay.com/doc2/detail?spm=0.0.0.0.E3tvGh&treeId=26&articleId=103286&docType=1SDK下载地址:http://doc.ope

微信支付教程系列之扫码支付

微信支付教程系列之扫码支付 http://www.cnblogs.com/nangong/p/9fa625bfb92a986125f0ba72704c46ec.html 今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添加好友的时候,可以通过输入对方的微信号,也可以扫一扫对方的二维码.扫码支付,作为,微信支付里面,不可或缺的一个功能,对商品的支付提供了极为方便的体验,用途也非常的多.例如我们在地铁.公交站常见

【原创分享&#183;微信支付】 C# 微信支付教程系列之扫码支付

微信支付教程系列之扫码支付 今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添加好友的时候,可以通过输入对方的微信号,也可以扫一扫对方的二维码.扫码支付,作为,微信支付里面,不可或缺的一个功能,对商品的支付提供了极为方便的体验,用途也非常的多.例如我们在地铁.公交站常见的那些自动售货机(不错,就是那种投硬币,就可以自动出货的那种机器)中都用到.以前,那种机器,只能通过投硬币或者纸币,但是,这里面也有一定的风险

支付宝支付-支付宝PC端扫码支付

前言 支付宝支付—沙箱环境使用支付宝支付-支付宝PC端扫码支付「本文」支付宝支付-手机浏览器H5支付「待写」 PC端扫码支付,其实就是就是 电脑网站支付,本文基于支付宝沙箱环境,不了解的可以看一下上边的链接. 废话不多说,直接进入主题. 下载运行测试Demo 官方Demo下载链接:电脑网站支付(Java) 下载后导入 IDEA 中运行如下图所示: 如果在导入运行过程遇到错误,请参考这篇文章:IDEA中导入支付宝电脑网站支付测试Demo遇到的错误 进行支付测试,注意付款要用沙箱环境提供的支付宝AP

JAVA微信扫码支付模式二功能实现以及回调

一.准备工作 首先吐槽一下微信关于支付这块,本身支持的支付模式就好几种,但是官方文档特别零散,连像样的JAVA相关的demo也没几个.本人之前没有搞过微信支付,一开始真是被它搞晕,折腾两天终于调通了,特此写下来,以享后人吧! 关于准备工作,就"微信扫码支付模式二"官方文档地址在这 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 可以先看看,实际上需要准备的东西有以下几个: 其中APP_ID和APP_SECRET

微信支付公的众号支付和扫码支付

公众号支付是手机端的微信公众号H5页面支付,这种支付方式必须是在微信内置浏览器发起. 扫码支付分为模式一和模式二,模式一主要为线下服务,该模式是先扫码,再生成订单,商户先为自己的商品生成二维码连接,然后用户扫码之后决定是否购买,二维码无过期时间,比如自动售卖机大多采用这种模式:模式二主要为线上电商服务,用户选择商品后生成订单,根据订单生成二维码,然后支付,该二维码为临时二维码. 开发流程 一.授权目录 官方文档说必须是精确目录,其实是二级或三级目录就可以了,太精确的可能还会出现不识别的情况.如果

微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc

一.场景:公司需要在网站上进行微信支付. 二.API:使用微信开放平台的接入微信支付 -扫码支付.微信支付开发者平台链接 三.分析: 接入扫码支付(包含PC网站支付)包含三个阶段,问这里只讲使用,也就是第2阶段的<启动设计和开发>. 点击查看开发者文档(扫码支付)后,这里感觉微信的文档没有支付宝好理解(稍微吐槽下~~~),不过我们忽略一切,直接进入模式二:模式二最简单直接,不需要在商户后台进行配置,推荐大家使用,微信也说流程更为简单,我这里也讲的是模式二,模式一大家有兴趣可以自行研究下. 如上

.NET MVC结构框架下的微信扫码支付模式二 API接口开发测试

直接上干货 ,我们的宗旨就是为人民服务.授人以鱼不如授人以渔.不吹毛求疵.不浮夸.不虚伪.不忽悠.一切都是为了社会共同进步,繁荣昌盛,小程序猿.大程序猿.老程序猿还是嫩程序猿,希望这个社会不要太急功近利 ,希望每个IT行业的BOSS要有良知,程序猿的青春年华都是无私默默奉献,都是拿命拼出来了现在的成就,如果卸磨杀驴,如果逼良为娼,请MM你的良心对得起你爹妈吗,你也有家,你也有小孩,你也有父母的. 在这里致敬程序猿, 致敬我们的攻城狮,致敬我们最可爱的人! 珍惜生命,换种活法也是依然精彩. Vie

ThinkPHP5微信扫码支付

1.把微信官网下载的demo放在根目录/vendor/目录下,这里我的是/vendor/wxpay_pc目录 2.把cert里面的文件替换成自己项目的证书(登陆微信商户平台,账户中心,API安全下载) 3.把/wxpay_pc/lib目录下的WxPay.Config.php文件里的信息改成自己的信息,只需改以下四个就行: 3.把example/目录下的notify.php改名为PayNotifyCallBack.php  不改也没事,我是为了和该文件里的类名保持一致 4.把里面require_o