java开发微信付款码支付

微信开发 专栏收录该内容
0 篇文章 0 订阅

@[clownss] java开发微信付款码支付

微信支付–付款码支付

写在前面的话,各位大佬,晚上好!今儿是小弟第一次发表博客,我是一名刚入行的程序员,写的不好或是不对的地方,希望各位见谅。还请各位大佬能够指导,给予小弟一份帮助。谢谢大家!今天写的是我最近研究的微信付款码支付的一个小demo。
官方地址:https://pay.weixin.qq.com/wiki/doc/api/index.html

1.支付方式

微信官方提供了以下几种支付方式:

  • 付款码支付:用户打开微信钱包-付款码的界面,商户扫码后提交完成支付

  • JSAPI支付:用户通过微信扫码、关注公众号等方式进入商家H5页面,并在微信内调用JSSDK完成支付

  • Native支付:用户打开“微信扫一扫”,扫描商户的二维码后完成支付

  • H5支付:用户在微信以外的手机浏览器请求微信支付的场景唤起微信支付

  • 小程序支付:用户在微信小程序中使用微信支付的场景

    我这里只是讨论的是 付款码支付

2.准备参数

微信付款码开发需要准备:appid,商户号,密钥

  • appid(公众账号ID )微信分配的公众账号ID(企业号corpid即为此appId)
  • mch_id (商户号 )微信支付分配的商户号
  • key(密钥)微信API密钥

2.1付款码支付开发流程

  • 第一步需要注册微信公众号,在微信公众号里面微信回给我们分配的开发者ID(AppID) 以及开发者密码(AppSecret) ,这两个需要我们妥善保管。appid在微信开发的几种模式都需要用到。

  • 第二步就是需要注册商户号了,这里注册就比较严格了。商户平台会给我们分配商户号(mch_id )

  • 第三步设置API密钥,简单流程就是:安装操作证书 -> 设置API密钥

    操作指引:可参考http://kf.qq.com/faq/161222NneAJf161222U7fARv.html

3.代码实现(简单开发)

这里主要写我在开发过程中具体实现,一个简单的jsp+servlet开发,需要下载官方的demo。

  • 到maven仓库下载需要的jar包wxpay-sdk-0.0.3.jardom4j-1.6.1.jar放到我们的项目中
  • 编写IWXPayDomain接口,官方demo里面也有这个接口
/**
 * 域名管理,实现主备域名自动切换
 */
public interface IWXPayDomain {
    /**
     * 上报域名网络状况
     * @param domain 域名。 比如:api.mch.weixin.qq.com
     * @param elapsedTimeMillis 耗时
     * @param ex 网络请求中出现的异常。
     *           null表示没有异常
     *           ConnectTimeoutException,表示建立网络连接异常
     *           UnknownHostException, 表示dns解析异常
     */
     void report(final String domain, long elapsedTimeMillis, final Exception ex);

    /**
     * 获取域名
     * @param config 配置
     * @return 域名
     */
     DomainInfo getDomain(final WXPayConfig config);

     class DomainInfo{
         /**
          * 域名
          */
        public String domain;
         /**
          * 该域名是否为主域名。例如:api.mch.weixin.qq.com为主域名
          */
        public boolean primaryDomain;
        public DomainInfo(String domain, boolean primaryDomain) {
            this.domain = domain;
            this.primaryDomain = primaryDomain;
        }

        @Override
        public String toString() {
            return "DomainInfo{" +
                    "domain='" + domain + '\'' +
                    ", primaryDomain=" + primaryDomain +
                    '}';
        }
    }
}
  • 编写MyConfig 类实现微信sdk里面的WXPayConfig 接口,这里面主要是准备我们自己的参数,就是上面准备的appid商户号密钥
public class MyConfig implements WXPayConfig {

    /** 加载证书  这里证书需要到微信商户平台进行下载*/
    private byte[] certData;

    public MyConfig() throws Exception {
        //证书只是撤销订单时会使用,在这里的demo中没有用到
        /*String certPath = "自己商户平台下载的证书";
        File file = new File(certPath);
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();*/
    }

    /**
     * 设置自己的appId ,商户号,密钥
     * @return
     */
    @Override
    public String getAppID() {
        return "自己的appId";
    }

    @Override
    public String getMchID() {
        return "自己的商户号";
    }

    @Override
    public String getKey() {
        return "自己的密钥";
    }

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

    @Override
    public int getHttpReadTimeoutMs() {
        return 10000;
    }

	/**
	*这里的方法,实现必须如下
	*/
    IWXPayDomain getWXPayDomain() {
        IWXPayDomain iwxPayDomain = new IWXPayDomain() {
            @Override
            public void report(String domain, long elapsedTimeMillis, Exception ex) {

            }
            @Override
            public DomainInfo getDomain(WXPayConfig config) {
                return new IWXPayDomain.DomainInfo("api.mch.weixin.qq.com", true);
            }
        };
        return iwxPayDomain;
    }
}
  • 编写我们的支付方法(接口)了
public class MyWXPay {

   private static final String PAY_SUCCESS = "SUCCESS";
   private static final String PAY_USERPAYING = "USERPAYING";

   private MyWXPay(){}

   private static Log log = LogFactory.getLog(MyWXPay.class);

   /**
    * 扫码支付
    * @throws Exception
    */
   public static String scanCodeToPay(String auth_code) throws Exception {
       MyConfig config = new MyConfig();
       WXPay wxpay = new WXPay(config);
       String out_trade_no = DateUtil.getCurrentTime();
       Map<String, String> map = new HashMap<>(16);
       map.put("attach", "订单额外描述");
       map.put("auth_code", auth_code);
       map.put("body", "付款码支付测试");
       map.put("device_info", "1000");
       map.put("nonce_str", WXPayUtil.generateNonceStr());
       map.put("out_trade_no", out_trade_no);
       map.put("spbill_create_ip", "14.17.22.52");
       map.put("total_fee", "2");
       //生成签名
       String sign = WXPayUtil.generateSignature(map, config.getKey());
       map.put("sign", sign);
       String mapToXml = null;
       try {
       	//调用微信的扫码支付接口
           Map<String, String> resp = wxpay.microPay(map);
           mapToXml = WXPayUtil.mapToXml(resp);
       } catch (Exception e) {
           e.printStackTrace();
           log.error("微信支付失败"+ e);
       }
       //判断支付是否成功
       String return_code = null;
       String result_code = null;
       String err_code_des = null;
       String err_code = null;
       //获取Document对象(主要是获取支付接口的返回信息)
       Document doc = DocumentHelper.parseText(mapToXml);
       //获取对象的根节点<xml>
       Element rootElement = doc.getRootElement();
       //获取对象的子节点
       List<Element> elements = rootElement.elements();
       for (Element element : elements) {
           if(element.getName().equals("return_code")){
               return_code = element.getTextTrim();
           } else if(element.getName().equals("result_code")){
               result_code = element.getTextTrim();
           } else if(element.getName().equals("err_code_des")){
               err_code_des = element.getTextTrim();
           } else if(element.getName().equals("err_code")){
               err_code = element.getTextTrim();
           }
       }
       if(PAY_SUCCESS.equals(return_code) && PAY_SUCCESS.equals(result_code)){
           log.info("微信免密支付成功!");
           return PAY_SUCCESS;
       } else if (PAY_USERPAYING.equals(err_code)){
           for(int i = 0; i < 4; i++){
               Thread.sleep(3000);
               Map<String, String> data = new HashMap<>(16);
               data.put("out_trade_no", out_trade_no);
               //调用微信的查询接口
               Map<String, String> orderQuery = wxpay.orderQuery(data);
               String orderResp = WXPayUtil.mapToXml(orderQuery);
               String trade_state = null;
               //获取Document对象
               Document orderDoc = DocumentHelper.parseText(orderResp);
               //获取对象的根节点<xml>
               Element rootElement1 = orderDoc.getRootElement();
               //获取对象的子节点
               List<Element> elements1 = rootElement1.elements();
               for (Element element : elements1) {
                   if(element.getName().equals("trade_state")){
                       trade_state = element.getTextTrim();
                   }
               }
               if(PAY_SUCCESS.equals(trade_state)){
                   log.info("微信加密支付成功!");
                   return PAY_SUCCESS;
               }
               log.info("正在支付" + orderResp);
           }
       }
       log.error("微信支付失败!");
       return err_code_des;
   }
}

我这里模拟了付款时需要输入密码,进行了三次轮询。里面的各个参数的含义,我这里就不详细写了,请参考官方文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1

  • 最后一步就是进行测试
@Test
    public void test4(){
        try {
            String result = MyWXPay.scanCodeToPay("请填写测试微信二维码信息");
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 工具类代码
public class DateUtil {
    
     private DateUtil(){
        throw new RuntimeException("不能被实列化!");
    }

    /**
     * 获取当前时间(14位)
     * @return
     */
    public static String getCurrentTime(){
        Date now = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return simpleDateFormat.format(now);
    }
    /**
     * 获取当前时间戳,单位秒(10位)
     * @return
     */
    public static long getCurrentTimestamp() {
        return System.currentTimeMillis()/1000;
    }

    /**
     * 获取当前时间戳,单位毫秒(13位)
     * @return
     */
    public static long getCurrentTimestampMs() {
        return System.currentTimeMillis();
    }

}

今天的分享就是这些了,希望能给你有所帮助,写的不好还请大家见谅。在下一篇博客里我想给大家介绍第二种支付方式JSAPI支付 ,希望得到大家的支持。谢谢大家!祝大家生活愉快,合家欢乐。

  • 9
    点赞
  • 15
    评论
  • 29
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值