精华内容
下载资源
问答
  • 什么样的二维码支付平台是合法的?哪些比较安全、靠谱?相信很多想从事相关行业创业的人都有这个疑问,当然在二维码支付业务热度居高不下的时期,如何选择一家综合实力比较靠谱并且合规的二维码支付平台,成为支付...

    什么样的二维码支付平台是合法的?哪些比较安全、靠谱?相信很多想从事相关行业创业的人都有这个疑问,当然在二维码支付业务热度居高不下的时期,如何选择一家综合实力比较靠谱并且合规的二维码支付平台,成为支付创业的重中之重,虽然努力很重要,但是选择是一个前提,选择不对就会导致努力就白费了。

     

    现在做支付的很多想做第三方平台的,但是第三方的都不是很好接,我这里给大家推荐下第四方二维码支付平台,给您一个参考。那么合法的二维码支付平台是怎样的呢?

    合法的二维码支付平台:支付FM

    支付FM为什么说是合法的,首先支付FM不托管资金,是通过技术手段让付款方直接看到收款方的收款码,通过扫码手段进行交易支付。

    用户量超过同行第四方服务商水准:支付FM庞大的用户基数

    目前超过400个城市的商户都在用支付FM收款,支付FM合作大中小企业过万家,为消费者提供千万次的扫码交易次数。获取了很多项支付相关荣誉,成为行业的一个标杆。

     

    支付FM:让支付更简单!(zhifu.fm)

    现在做支付平台的很多很多,但是二清平台依然存在,靠回笼投资人的资金的企业依然存在,支付FM支付服务商提醒大家要擦亮眼睛,支付FM二维码支付平台是一个合规的第四方支付企业,具有安全、高效、稳定的特点,欢迎大家体验!

    展开全文
  • 在蚂蚁金服开发平台下载demo 打开 TradePayDemo 项目,里面的main可以直接运行,在配置文件zfbinfo.properties中改为自己支付宝的信息 # 支付宝网关名、partnerId和appId open_api_domain = ...

    在蚂蚁金服开发平台下载demo
    在这里插入图片描述
    打开 TradePayDemo 项目,里面的main可以直接运行,在配置文件zfbinfo.properties中改为自己支付宝的信息

    # 支付宝网关名、partnerId和appId
    open_api_domain = https://openapi.alipay.com/gateway.do
    mcloud_api_domain =
    pid = 
    appid = #申请应用并签约后会有一个有效的appid,应用名称一个月只能修改一次
    
    # RSA私钥、公钥和支付宝公钥
    private_key = 
    public_key =   #这里的公钥为支付宝产生的应用公钥
    
    #SHA1withRsa对应支付宝公钥
    alipay_public_key = 
    
    # 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
    sign_type = RSA2
    # 当面付最大查询次数和查询间隔(毫秒)
    max_query_retry = 5
    query_duration = 5000
    
    # 当面付最大撤销次数和撤销间隔(毫秒)
    max_cancel_retry = 3
    cancel_duration = 2000
    
    # 交易保障线程第一次调度延迟和调度间隔(秒)
    heartbeat_delay = 5
    heartbeat_duration = 900
    

    二维码预下单,修改必要信息即可直接运行

    package com.ys.demo.serviceImpl;
    
    import com.alipay.api.*;
    import com.alipay.api.request.AlipayTradeCancelRequest;
    import com.alipay.api.request.AlipayTradeRefundRequest;
    import com.alipay.api.response.AlipayTradeCancelResponse;
    import com.alipay.api.response.AlipayTradePrecreateResponse;
    import com.alipay.api.response.AlipayTradeRefundResponse;
    import com.alipay.demo.trade.config.Configs;
    import com.alipay.demo.trade.model.ExtendParams;
    import com.alipay.demo.trade.model.GoodsDetail;
    import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
    import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
    import com.alipay.demo.trade.service.AlipayMonitorService;
    import com.alipay.demo.trade.service.AlipayTradeService;
    import com.alipay.demo.trade.service.impl.AlipayMonitorServiceImpl;
    import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
    import com.alipay.demo.trade.service.impl.AlipayTradeWithHBServiceImpl;
    import com.ys.demo.domain.Order;
    import com.ys.demo.service.AlipayService;
    import com.ys.demo.utils.payUtil;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    @Service
    public class AlipayServiceImpl implements AlipayService {
    
        private static Log log = LogFactory.getLog(AlipayServiceImpl.class);
    
        // 支付宝当面付2.0服务
        private static AlipayTradeService tradeService;
        // 支付宝当面付2.0服务(集成了交易保障接口逻辑)
        @SuppressWarnings("unused")
    	private static AlipayTradeService   tradeWithHBService;
    
        // 支付宝交易保障接口服务,供测试接口api使用,请先阅读readme.txt
        @SuppressWarnings("unused")
    	private static AlipayMonitorService monitorService;
        static {
            /** 一定要在创建AlipayTradeService之前调用Configs.init()设置默认参数
             *  Configs会读取classpath下的zfbinfo.properties文件配置信息,如果找不到该文件则确认该文件是否在classpath目录
             */
            Configs.init("zfbinfo.properties");
    
            /** 使用Configs提供的默认参数
             *  AlipayTradeService可以使用单例或者为静态成员对象,不需要反复new
             */
            tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
    
            // 支付宝当面付2.0服务(集成了交易保障接口逻辑)
            tradeWithHBService = new AlipayTradeWithHBServiceImpl.ClientBuilder().build();
    
            /** 如果需要在程序中覆盖Configs提供的默认参数, 可以使用ClientBuilder类的setXXX方法修改默认参数 否则使用代码中的默认设置 */
            monitorService = new AlipayMonitorServiceImpl.ClientBuilder()
                    .setGatewayUrl("http://mcloudmonitor.com/gateway.do").setCharset("GBK")
                    .setFormat("json").build();
        }
        /**
         * 支付宝二维码
         * @param order
         * @author joke
         */
        @Override
        public String aliPay(Order order) throws Exception {
    
                // (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线,
                String outTradeNo = order.getOrderId();
                // (必填) 订单标题,粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
                String subject = "消费";
    
                // (必填) 订单总金额,单位为元,不能超过1亿元
                // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
                String totalAmount = String.valueOf(order.getPrice());//总金额,单位元
                // (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段
                // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
                String undiscountableAmount = "0";
    
                // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)
                // 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID
                String sellerId = "";
    
                // 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"
                String body = "消费";
    
                // 商户操作员编号,添加此参数可以为商户操作员做销售统计
                String operatorId = order.getOrderId();
    
                // (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
                String storeId = "test_store_id";
    
                // 业务扩展参数,目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法),详情请咨询支付宝技术支持
                ExtendParams extendParams = new ExtendParams();
                extendParams.setSysServiceProviderId("");
    
                // 支付超时,定义为1分钟
                String timeoutExpress = "1m";
    
                // 商品明细列表,需填写购买商品详细信息,
                List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
                // 创建一个商品信息,参数含义分别为商品id(使用国标)、名称、单价(单位为分)、数量,如果需要添加商品类别,详见GoodsDetail
                GoodsDetail goods1 = GoodsDetail.newInstance(order.getOrderId(), "消费", order.getPrice(), 1);
                // 创建好一个商品后添加至商品明细列表
                goodsDetailList.add(goods1);
    
                // 创建扫码支付请求builder,设置请求参数
                AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                        .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
                        .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
                        .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
                        .setTimeoutExpress(timeoutExpress)
                        .setNotifyUrl("")//支付宝回调地址
                        .setGoodsDetailList(goodsDetailList);
    
                AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
                String alipayUrl = null;
                switch (result.getTradeStatus()) {
                    case SUCCESS:
                        log.info("支付宝预下单成功: )");
    
                        AlipayTradePrecreateResponse response = result.getResponse();
                        dumpResponse(response);
                        alipayUrl = response.getQrCode();
    
                        // 需要修改为运行机器上的路径
    //                    String filePath = String.format("D:/qr-%s.png",
    //                            response.getOutTradeNo());
    //                    log.info("filePath:" + filePath);
    //                                    ZxingUtils.getQRCodeImge(response.getQrCode(), 256, filePath);
                        break;
    
                    case FAILED:
                        log.error("支付宝预下单失败!!!");
                        break;
    
                    case UNKNOWN:
                        log.error("系统异常,预下单状态未知!!!");
                        break;
    
                    default:
                        log.error("不支持的交易状态,交易返回异常!!!");
                        break;
                }
                return alipayUrl;
            }
        // 简单打印应答
        @Override
        public void dumpResponse(AlipayResponse response) {
            if (response != null) {
                log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
                if (StringUtils.isNotEmpty(response.getSubCode())) {
                    log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
                            response.getSubMsg()));
                }
                log.info("body:" + response.getBody());
            }
        }
    
        /**
         * 支付宝退款
         * @param
         * @author joke
         */
        @Override
        public String refund(Order order) throws AlipayApiException{
            AlipayClient alipayClient = new DefaultAlipayClient(Configs.getOpenApiDomain(),Configs.getAppid(),Configs.getPrivateKey(),"json","UTF-8",Configs.getAlipayPublicKey(),"RSA2");
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            request.setBizContent("{" +
                    "\"out_trade_no\":\"" + order.getOrderId() + "\"," +
                    "\"refund_amount\":\"" + order.getPrice() + "\"," +
                    "\"refund_currency\":\"" + payUtil.REFUND_FEE_TYPE + "\"," +
                    "\"refund_reason\":\"" + payUtil.REFUND_DESC + "\"," +
                    "\"out_request_no\":\"" + order.getOutRefundNo() + "\"," +
                    "  }");
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            String result = "success";
            if(response.isSuccess()){
                System.out.println("调用成功");
            } else {
                result = "failure";
                System.out.println("调用失败");
            }
            return result;
        }
    
        /**
         * 支付宝撤销
         * @param order
         * @author joke
         */
        @Override
        public String revoke(Order order)throws AlipayApiException {
            //AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","UTF-8","alipay_public_key","RSA2");
            AlipayClient alipayClient = new DefaultAlipayClient(Configs.getOpenApiDomain(),Configs.getAppid(),Configs.getPrivateKey(),"json","UTF-8",Configs.getAlipayPublicKey(),"RSA2");
            AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
            request.setBizContent("{" +
                    "\"out_trade_no\":" + "\"" + order.getOrderId()+ "\"" + " }");
            String result = "1";
            AlipayTradeCancelResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                System.out.println("调用成功");
            } else {
                result = "0";
                System.out.println("调用失败");
            }
    
            return result;
        }
    
    
    }
    
    

    支付宝回调接口,ip需与域名绑定

    package com.ys.demo.controller;
    
    import com.alibaba.fastjson.JSON;
    import com.alipay.api.AlipayApiException;
    import com.alipay.api.internal.util.AlipaySignature;
    import com.ys.demo.domain.Order;
    import com.ys.demo.service.OrderService;
    import com.ys.demo.serviceImpl.MQTTPublish;
    import com.ys.demo.utils.AlipayConfig;
    import com.ys.demo.utils.AlipayNotifyParam;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.eclipse.paho.client.mqttv3.MqttMessage;
    import org.json.JSONObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    @RestController
    public class AlipayCallbackController {
        private static Log logger = LogFactory.getLog(AlipayCallbackController.class);
    
        @Autowired
        private AlipayConfig alipayConfig; // 支付宝支付配置
    
        @Autowired
        private OrderService orderService;
    
        @Autowired
        private MQTTPublish mqttPublish;
    
        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        private ExecutorService executorService = Executors.newFixedThreadPool(20);
        @RequestMapping("alipayTest")
        public String method(){
            logger.info("Alipay callback!");
            return "Alipay callback!";
        }
    
        /**
         * <pre>
         * 第一步:验证签名,签名通过后进行第二步
         * 第二步:按一下步骤进行验证
         * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
         * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
         * 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
         * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
         * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
         * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
         * </pre>
         *
         * @param request
         * @return
         */
        @RequestMapping("alipayCallback")
        public String callback(HttpServletRequest request) throws Exception{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
            String paramsJson = JSON.toJSONString(params);///支付宝回调的参数
            logger.info("支付宝回调,{}", new Throwable(paramsJson));
    		String trade_status = params.get("trade_status");支付返回结果
                try {
                    // 调用SDK验证签名
                    boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipay_public_key(),
                            alipayConfig.getCharset(), alipayConfig.getSigntype());
                    if (signVerified) {
                        logger.info("支付宝回调签名认证成功");
                        // 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1/2/3/4二次校验,校验成功后在response中返回success,校验失败返回failure
                        this.check(params);
                        // 另起线程处理业务
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {
                                
                                try{
                                    // 支付成功业务逻辑处理
                                    if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) {
                                       /业务逻辑处理
                                    } else {
                                        ///业务逻辑处理
                                    }
                                }catch (Exception e){
                                    logger.error("Business handling exception!");
                                }
                            }
                        });
                        return "success";
                    } else {
                        logger.info("支付宝回调签名认证失败,signVerified=false, paramsJson:{}"+ paramsJson);
                        //认证签名失败,业务逻辑处理
                        return "failure";
                    }
                } catch (AlipayApiException e) {
                    logger.error("支付宝回调签名认证失败,paramsJson:{},errorMsg:{}"+ paramsJson, e);
                }
            }
    
        // 将request中的参数转换成Map
        private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
            Map<String, String> retMap = new HashMap<String, String>();
    
            Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
    
            for (Map.Entry<String, String[]> entry : entrySet) {
                String name = entry.getKey();
                String[] values = entry.getValue();
                int valLen = values.length;
    
                if (valLen == 1) {
                    retMap.put(name, values[0]);
                } else if (valLen > 1) {
                    StringBuilder sb = new StringBuilder();
                    for (String val : values) {
                        sb.append(",").append(val);
                    }
                    retMap.put(name, sb.toString().substring(1));
                } else {
                    retMap.put(name, "");
                }
            }
    
            return retMap;
        }
    
        private AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
            String json = JSON.toJSONString(params);
            return JSON.parseObject(json, AlipayNotifyParam.class);
        }
    
        /**
         * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
         * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
         * 3、校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
         * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
         * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
         * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
         *
         * @param params
         * @throws AlipayApiException
         */
        private void check(Map<String, String> params) throws AlipayApiException {
            String outTradeNo = params.get("out_trade_no");
            // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
            Order order = orderService.selectByOrderId(outTradeNo);
            if (order == null) {
                logger.error("out_trade_no错误" + sdf);
                throw new AlipayApiException("out_trade_no错误");
            }
            // 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
            // 3、校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
            // 第三步可根据实际情况省略
            // 4、验证app_id是否为该商户本身。
            if (!params.get("app_id").equals(alipayConfig.getAppid())) {
                logger.error(outTradeNo + ",app_id不一致" + sdf);
                throw new AlipayApiException("app_id不一致");
            }
        }
        public MqttMessage getMsg(MqttMessage msg, String jsonS) {
            msg.setQos(1);
            msg.setRetained(true);
            msg.setPayload(jsonS.getBytes());
            return msg;
        }
    }
    
    

    微信二维码支付

    package com.ys.demo.serviceImpl;
    
    
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.EncodeHintType;
    import com.google.zxing.MultiFormatWriter;
    import com.google.zxing.WriterException;
    import com.google.zxing.common.BitMatrix;
    import com.ys.demo.domain.Order;
    import com.ys.demo.service.WeChatService;
    import com.ys.demo.utils.wechat.*;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.io.File;
    import java.util.Hashtable;
    import java.util.Map;
    import java.util.SortedMap;
    import java.util.TreeMap;
    
    @Service
    public class WeChatServiceImpl implements WeChatService {
        private WXPayConstants.SignType signType;
        private boolean autoReport;
        private boolean useSandbox;
        @SuppressWarnings("unused")
    	private String notifyUrl;
        private WXPayRequest wxPayRequest;
        /**
         * 作用:预下单<br>
         * 场景:扫码支付<br>
         * @param order 读超时时间,单位是毫秒
         * @return API返回数据
         * @throws Exception
         */
    	@Override
    	public String weixinPay(Order order) throws Exception {
    		try{
                //String out_trade_no = "" + System.currentTimeMillis(); //订单号 (调整为自己的生产逻辑)
    
                // 账号信息
                String appid = PayConfigUtil.APP_ID;  // appid
                //String appsecret = PayConfigUtil.APP_SECRET; // appsecret
                String mch_id = PayConfigUtil.MCH_ID; // 商业号
                String key = PayConfigUtil.API_KEY; // key
    
                String currTime = PayToolUtil.getCurrTime();
                String strTime = currTime.substring(8, currTime.length());
                String strRandom = PayToolUtil.buildRandom(4) + "";
                String nonce_str = strTime + strRandom;
    
                // 获取发起电脑 ip
                String spbill_create_ip = PayConfigUtil.CREATE_IP;
                // 回调接口
                String notify_url = PayConfigUtil.NOTIFY_URL;
                String trade_type = "NATIVE";
                SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
                packageParams.put("appid", appid);
                packageParams.put("mch_id", mch_id);
                packageParams.put("nonce_str", nonce_str);
                packageParams.put("body", "消费");  //(调整为自己的名称)
                packageParams.put("out_trade_no", order.getOrderId());
                packageParams.put("total_fee", String.valueOf(order.getPrice())); //价格的单位为分
                packageParams.put("spbill_create_ip", spbill_create_ip);
                packageParams.put("notify_url", notify_url);
                packageParams.put("trade_type", trade_type);
                //packageParams.put("", "");
                String sign = PayToolUtil.createSign("UTF-8", packageParams,key); //签名
                packageParams.put("sign", sign);
                String requestXML = PayToolUtil.getRequestXml(packageParams); //将请求参数转换为xml格式的string
                String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);  //连接微信,并返回result
                @SuppressWarnings("rawtypes")
    			Map map = XMLUtil4jdom.doXMLParse(resXml);
                String urlCode = (String) map.get("code_url");
    //            QRUtil.qwqe(urlCode);
                return urlCode;
            }catch (Exception e){
    		    System.out.println("ss"+ e.getMessage());
            }
            return  null;
    	}
    
        public void qrcode(String code) throws Exception {
            try {
                int width = 300;
                int height = 300;
                //二维码的图片格式
                String format = "gif";
                Hashtable hints = new Hashtable();
                //内容所使用编码
                hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
                BitMatrix bitMatrix;
                try {
                    bitMatrix = new MultiFormatWriter().encode(code, BarcodeFormat.QR_CODE, width, height, hints);
                    File file = new File("d:"+File.separator+"new.gif");
    //                QRUtil.writeToStream(bitMatrix, format, file);
                } catch (WriterException e) {
                    e.printStackTrace();
                }
    
            } catch (Exception e) {
            }
        }
    
        /**
         * 作用:申请退款<br>
         * 场景:刷卡支付、公共号支付、扫码支付、APP支付<br>
         * 其他:需要证书
         * @param reqData 向wxpay post的请求数据
         * @param connectTimeoutMs 连接超时时间,单位是毫秒
         * @param readTimeoutMs 读超时时间,单位是毫秒
         * @return API返回数据
         * @throws Exception
         */
        @Override
        public String refund(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
            String url;
            if (this.useSandbox) {
                url = WXPayConstants.SANDBOX_REFUND_URL_SUFFIX;
            }
            else {
                url = WXPayConstants.REFUND_URL_SUFFIX;
            }
            String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
            return this.processResponseXml(respXml);
        }
        /**
         * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign <br>
         * 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口
         *
         * @param reqData
         * @return
         * @throws Exception
         */
        @Override
        public Map<String, String> fillRequestData(Map<String, String> reqData) throws Exception {
            //reqData.put("appid", config.getAppID());
            reqData.put("appid", PayConfigUtil.APP_ID);
            //reqData.put("mch_id", config.getMchID());
            reqData.put("mch_id", PayConfigUtil.MCH_ID);
            reqData.put("nonce_str", WXPayUtil.generateNonceStr());
            if (WXPayConstants.SignType.MD5.equals(this.signType)) {
                reqData.put("sign_type", WXPayConstants.MD5);
            }
            else if (WXPayConstants.SignType.HMACSHA256.equals(this.signType)) {
                reqData.put("sign_type", WXPayConstants.HMACSHA256);
            }
            //reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType));
            reqData.put("sign", WXPayUtil.generateSignature(reqData, PayConfigUtil.API_KEY, this.signType));
            return reqData;
        }
    
        /**
         * 需要证书的请求
         * @param urlSuffix String
         * @param reqData 向wxpay post的请求数据  Map
         * @param connectTimeoutMs 超时时间,单位是毫秒
         * @param readTimeoutMs 超时时间,单位是毫秒
         * @return API返回数据
         * @throws Exception
         */
        @Override
        public String requestWithCert(String urlSuffix, Map<String, String> reqData,
                                      int connectTimeoutMs, int readTimeoutMs) throws Exception {
            String msgUUID= reqData.get("nonce_str");
            String reqBody = WXPayUtil.mapToXml(reqData);
    
            String resp = this.wxPayRequest.requestWithCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, this.autoReport);
            return resp;
        }
    
        /**
         * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。
         * @param xmlStr API返回的XML格式数据
         * @return Map类型数据
         * @throws Exception
         */
    //    @Override
    //    public Map<String, String> processResponseXml(String xmlStr) throws Exception {
    //        String RETURN_CODE = "return_code";
    //        String return_code;
    //        Map<String, String> respData = WXPayUtil.xmlToMap(xmlStr);
    //        if (respData.containsKey(RETURN_CODE)) {
    //            return_code = respData.get(RETURN_CODE);
    //        }
    //        else {
    //            throw new Exception(String.format("No `return_code` in XML: %s", xmlStr));
    //        }
    //
    //        if (return_code.equals(WXPayConstants.FAIL)) {
    //            return respData;
    //        }
    //        else if (return_code.equals(WXPayConstants.SUCCESS)) {
    //            if (this.isResponseSignatureValid(respData)) {
    //                return respData;
    //            }
    //            else {
    //                throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr));
    //            }
    //        }
    //        else {
    //            throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr));
    //        }
    //    }
        @Override
        public String processResponseXml(String xmlStr) throws Exception {
            String RETURN_CODE = "return_code";
            String return_code;
            Map<String, String> respData = WXPayUtil.xmlToMap(xmlStr);
            if (respData.containsKey(RETURN_CODE)) {
                return_code = respData.get(RETURN_CODE);
            }
            else {
                return "failure";
                //throw new Exception(String.format("No `return_code` in XML: %s", xmlStr));
            }
    
            if (return_code.equals(WXPayConstants.FAIL)) {
                return "failure";
            }
            else if (return_code.equals(WXPayConstants.SUCCESS)) {
                if (this.isResponseSignatureValid(respData)) {
                    return "success";
                }
                else {
                    return "failure";
                    //throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr));
                }
            }
            else {
                return "failure";
                //throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr));
            }
        }
    
        /**
         * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。
         *
         * @param reqData 向wxpay post的请求数据
         * @return 签名是否有效
         * @throws Exception
         */
        @Override
        public boolean isResponseSignatureValid(Map<String, String> reqData) throws Exception {
            // 返回数据的签名方式和请求中给定的签名方式是一致的
            return WXPayUtil.isSignatureValid(reqData, PayConfigUtil.API_KEY, this.signType);
        }
    }
    
    

    微信回调接口,域名和ip需绑定,否则不能回调

    package com.ys.demo.controller;
    
    import com.ys.demo.domain.Order;
    import com.ys.demo.utils.wechat.PayConfigUtil;
    import com.ys.demo.utils.wechat.PayToolUtil;
    import com.ys.demo.utils.wechat.XMLUtil4jdom;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.eclipse.paho.client.mqttv3.MqttMessage;
    import org.jdom2.JDOMException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.ui.ModelMap;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    @RestController
    public class PayCallBackController{
        private static Log logger = LogFactory.getLog(PayCallBackController.class);
    //    @Autowired
    //    private OrderService orderService;
    
        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        @RequestMapping("wxpayTtest")
        public String method(){
            logger.info("wxpay callback!");
            return "wxpay callback!";
        }
        /*
        * 微信回调函数
        * */
        @RequestMapping("weixinNotify")
        public void wechatCallBack(HttpServletRequest request, HttpServletResponse response,
                                   ModelMap modelMap)  throws JDOMException, Exception{
            logger.info("微信回调");
            MqttMessage msg = new MqttMessage();
            //读取参数
            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成map */
            Map<String, String> m = new HashMap<String, String>();
            m = XMLUtil4jdom.doXMLParse(sb.toString());
    
            //过滤空 设置 TreeMap
            SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
            Iterator it = m.keySet().iterator();
            while (it.hasNext()) {
                String parameter = (String) it.next();
                String parameterValue = m.get(parameter);
    
                String v = "";
                if(null != parameterValue) {
                    v = parameterValue.trim();
                }
                packageParams.put(parameter, v);
            }
    
            // 账号信息
            String key = PayConfigUtil.API_KEY; //key
            String orderId = (String)packageParams.get("out_trade_no");
    
    //        Order order = orderService.selectByOrderId(orderId);
    //        if (StringUtils.isEmpty(order)){
    //            return;
    //        }
            String price = (String)packageParams.get("price");
    
            if(PayToolUtil.isTenpaySign("UTF-8", packageParams,key)) {
                String resXml = "";
                if("SUCCESS".equals((String)packageParams.get("result_code"))){
                    //执行自己的业务逻辑
                    request.getSession().setAttribute("_PAY_RESULT", "OK");
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                } else {
                    //执行自己的业务逻辑
                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                }
                BufferedOutputStream out = new BufferedOutputStream(
                        response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } else{
                logger.error(sdf+"通知签名验证失败:"+packageParams);
            }
        }
    
    }
    
    
    展开全文
  • 点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐]♪点击上方绿标 收听java实现微信支付宝等多个支付平台合一的二维码支付(SSM框架)整体思路:实现微信支付...
        

    点击上方[全栈开发者社区]右上角[...][设为星标⭐]

    640?

    ♪ 点击上方绿标 收听java实现微信支付宝等多个支付平台合一的二维码支付(SSM框架)

    整体思路:

    实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是spring springmvc mybatis 框架,maven管理。其实如果支付,不需要mybatis也能实现,代码和本人见解还需大神指教。流程和思路:**用户点击支付**-->**出现一次支付密码,并且带有时间限制**-->**扫描二维码跳转后台**-->**后台判断是微信支付还是支付宝支付**

    1.整体架构:

    640?wx_fmt=png

    2.配置编译的文件目录

    640?wx_fmt=png

    3.pom.xml,其中qrcode.qrcode、qrcode.swetake是从本地编译到maven库中,因为网络maven中没有。

    <?xml version="1.0"?>	
    <project	
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"	
        xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">	
        <modelVersion>4.0.0</modelVersion>	
        <parent>	
            <groupId>fanghuai</groupId>	
            <artifactId>nbt</artifactId>	
            <version>0.0.1-SNAPSHOT</version>	
        </parent>	
        <groupId>com.nbt.qrcoder</groupId>	
        <artifactId>nbt-qrcode</artifactId>	
        <version>0.0.1-SNAPSHOT</version>	
        <packaging>war</packaging>	
        <name>nbt-qrcode Maven Webapp</name>	
        <url>http://maven.apache.org</url>	
        <properties>	
            <spring.version>4.1.3.RELEASE</spring.version>	
            <mybatis.version>3.2.8</mybatis.version>	
            <mybatis.spring.version>1.2.2</mybatis.spring.version>	
            <mybatis.paginator.version>1.2.15</mybatis.paginator.version>	
            <mysql.version>5.1.32</mysql.version>	
            <slf4j.version>1.6.4</slf4j.version>	
            <jackson.version>2.4.2</jackson.version>	
            <druid.version>1.0.9</druid.version>	
            <jstl.version>1.2</jstl.version>	
            <servlet-api.version>2.5</servlet-api.version>	
            <jsp-api.version>2.0</jsp-api.version>	
            <commons-lang3.version>3.3.2</commons-lang3.version>	
            <commons-io.version>1.3.2</commons-io.version>	
            <commons-net.version>3.3</commons-net.version>	
            <pagehelper.version>4.0.0</pagehelper.version>	
    	
        </properties>	
        <dependencies>	
            <dependency>	
                <groupId>junit</groupId>	
                <artifactId>junit</artifactId>	
                <version>3.8.1</version>	
                <scope>test</scope>	
            </dependency>	
            <!-- qrcode -->	
            <dependency>	
                <groupId>qrcode.qrcode</groupId>	
                <artifactId>qrcode</artifactId>	
                <version>1.0</version>	
            </dependency>	
            <dependency>	
                <groupId>qrcode.swetake</groupId>	
                <artifactId>swetake</artifactId>	
                <version>1.0</version>	
            </dependency>	
    	
            <!-- 日志处理 -->	
            <dependency>	
                <groupId>org.slf4j</groupId>	
                <artifactId>slf4j-log4j12</artifactId>	
                <version>${slf4j.version}</version>	
            </dependency>	
            <!-- Mybatis -->	
            <dependency>	
                <groupId>org.mybatis</groupId>	
                <artifactId>mybatis</artifactId>	
                <version>${mybatis.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>org.mybatis</groupId>	
                <artifactId>mybatis-spring</artifactId>	
                <version>${mybatis.spring.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>com.github.miemiedev</groupId>	
                <artifactId>mybatis-paginator</artifactId>	
                <version>${mybatis.paginator.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>com.github.pagehelper</groupId>	
                <artifactId>pagehelper</artifactId>	
                <version>${pagehelper.version}</version>	
            </dependency>	
            <!-- MySql -->	
            <dependency>	
                <groupId>mysql</groupId>	
                <artifactId>mysql-connector-java</artifactId>	
                <version>${mysql.version}</version>	
            </dependency>	
            <!-- 连接池 -->	
            <dependency>	
                <groupId>com.alibaba</groupId>	
                <artifactId>druid</artifactId>	
                <version>${druid.version}</version>	
            </dependency>	
            <!-- Spring -->	
            <dependency>	
                <groupId>org.springframework</groupId>	
                <artifactId>spring-context</artifactId>	
                <version>${spring.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>org.springframework</groupId>	
                <artifactId>spring-beans</artifactId>	
                <version>${spring.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>org.springframework</groupId>	
                <artifactId>spring-webmvc</artifactId>	
                <version>${spring.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>org.springframework</groupId>	
                <artifactId>spring-jdbc</artifactId>	
                <version>${spring.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>org.springframework</groupId>	
                <artifactId>spring-aspects</artifactId>	
                <version>${spring.version}</version>	
            </dependency>	
            <!-- JSP相关 -->	
            <dependency>	
                <groupId>jstl</groupId>	
                <artifactId>jstl</artifactId>	
                <version>${jstl.version}</version>	
            </dependency>	
            <dependency>	
                <groupId>javax.servlet</groupId>	
                <artifactId>servlet-api</artifactId>	
                <version>${servlet-api.version}</version>	
                <scope>provided</scope>	
            </dependency>	
            <dependency>	
                <groupId>javax.servlet</groupId>	
                <artifactId>jsp-api</artifactId>	
                <version>${jsp-api.version}</version>	
                <scope>provided</scope>	
            </dependency>	
        </dependencies>	
        <build>	
            <finalName>nbt-qrcode</finalName>	
        </build>	
    </project>

    4.二维码相关属性(Model)

    package com.nbt.util;	
    import java.awt.image.BufferedImage;	
    import jp.sourceforge.qrcode.data.QRCodeImage;	
    	
     public   class J2SEImage implements QRCodeImage { 	
            BufferedImage bufImg; 	
            public J2SEImage(BufferedImage bufImg) { 	
                this.bufImg = bufImg; 	
            } 	
            public int getWidth() { 	
                return bufImg.getWidth(); 	
            } 	
            public int getHeight() { 	
                return bufImg.getHeight(); 	
            } 	
            public int getPixel(int x, int y) { 	
                return bufImg.getRGB(x, y); 	
            } 	
        }

    5.二维码生成代码

    package com.nbt.util;	
    	
    import java.awt.Color;	
    import java.awt.Graphics2D;	
    import java.awt.image.BufferedImage;	
    import java.io.File;	
    import java.io.IOException;	
    	
    import javax.imageio.ImageIO;	
    	
    import jp.sourceforge.qrcode.QRCodeDecoder;	
    import jp.sourceforge.qrcode.exception.DecodingFailedException;	
    	
    import com.swetake.util.Qrcode;	
    	
    public class QRCode {	
    	
         /**	
         * 生成二维码(QRCode)图片	
         * @param content  二维码内容	
         * @param imgPath 存放二维位置	
         */ 	
        public static  void encoderQRCode(BuildQRCode bc) { 	
    	
            try { 	
                Qrcode qrcodeHandler = new Qrcode(); 	
                qrcodeHandler.setQrcodeErrorCorrect('M'); 	
                qrcodeHandler.setQrcodeEncodeMode('B'); 	
                qrcodeHandler.setQrcodeVersion(7); 	
                System.out.println(bc.getContent()); 	
                byte[] contentBytes = bc.getContent().getBytes("gb2312"); 	
                BufferedImage bufImg = new BufferedImage(140, 140, 	
                        BufferedImage.TYPE_INT_RGB); 	
                Graphics2D gs = bufImg.createGraphics(); 	
                gs.setBackground(Color.WHITE); 	
                gs.clearRect(0, 0, 140, 140); 	
                // 设定图像颜色> BLACK 	
                gs.setColor(Color.BLACK); 	
                // 设置偏移量 不设置可能导致解析出错 	
                int pixoff = 2; 	
                // 输出内容> 二维码 	
                if (contentBytes.length > 0 && contentBytes.length < 120) { 	
                    boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes); 	
                    for (int i = 0; i < codeOut.length; i++) { 	
                        for (int j = 0; j < codeOut.length; j++) { 	
                            if (codeOut[j][i]) { 	
                                gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3); 	
                            } 	
                        } 	
                    } 	
                } else { 	
                    System.err.println("QRCode content bytes length = " + contentBytes.length + " not in [ 0,120 ]. "); 	
                } 	
                gs.dispose(); 	
                bufImg.flush(); 	
                File imgFile = new File(bc.getImgPath()); 	
                // 生成二维码QRCode图片 	
                ImageIO.write(bufImg, "png", imgFile); 	
    	
            } catch (Exception e) { 	
    	
                e.printStackTrace(); 	
            } 	
        } 	
    	
        /**	
         * 解码二维码	
         * @param imgPath	
         * @return String	
         */ 	
        public static  String decoderQRCode(String imgPath) { 	
            // QRCode 二维码图片的文件 	
            File imageFile = new File(imgPath); 	
            BufferedImage bufImg = null; 	
            String decodedData = null; 	
            try { 	
                bufImg = ImageIO.read(imageFile); 	
                QRCodeDecoder decoder = new QRCodeDecoder(); 	
                decodedData = new String(decoder.decode(new J2SEImage(bufImg))); 	
                // try { 	
                // System.out.println(new String(decodedData.getBytes("gb2312"), 	
                // "gb2312")); 	
                // } catch (Exception e) { 	
                // // TODO: handle exception 	
                // } 	
            } catch (IOException e) { 	
                System.out.println("Error: " + e.getMessage()); 	
                e.printStackTrace(); 	
            } catch (DecodingFailedException dfe) { 	
                System.out.println("Error: " + dfe.getMessage()); 	
                dfe.printStackTrace(); 	
            } 	
            return decodedData; 	
        } 	
    	
    	
        public static void main(String[] args) {	
    	
        //生成二维码	
             String imgPath = "D:/test/Michael_QRCode.png"; 	
             String content = "http://www.baidu.com"; 	
             BuildQRCode bc = new BuildQRCode(imgPath,content);	
             encoderQRCode(bc); 	
             System.out.println("encoder QRcode success"); 	
    	
    	
         //解读二维码	
             String decoderContent =decoderQRCode(imgPath); 	
             System.out.println("解析结果如下:"); 	
             System.out.println(decoderContent); 	
             System.out.println("========decoder success!!!");	
         } 	
    }

    6.Controller相关代码(jsp页面要通过流的形式放在页面上,不然二维码显示不出来。)

    package com.nbt.controller;	
    	
    import java.io.File;	
    import java.io.FileInputStream;	
    import java.io.IOException;	
    import java.io.OutputStream;	
    import java.text.SimpleDateFormat;	
    import java.util.Calendar;	
    import java.util.Map;	
    	
    import javax.servlet.http.HttpServletRequest;	
    import javax.servlet.http.HttpServletResponse;	
    	
    import org.apache.log4j.Logger;	
    import org.springframework.stereotype.Controller;	
    import org.springframework.ui.Model;	
    import org.springframework.web.bind.annotation.RequestMapping;	
    import org.springframework.web.bind.annotation.RequestParam;	
    	
    import com.mysql.jdbc.StringUtils;	
    import com.nbt.util.BuildQRCode;	
    import com.nbt.util.QRCode;	
    @Controller	
    @RequestMapping("/qr")	
    public class QRCodeController {	
    	
        private static Logger log = Logger.getLogger(QRCodeController.class);	
    	
    	
        /**	
         * 跳转到二维码页面	
         * @param request	
         * @return	
         */	
        @RequestMapping("/toShowQRCode.do")	
        public String showQRCode(HttpServletRequest request){	
            log.info("跳转到二维码页面...");	
            return "qr";    	
        }	
    	
        /**	
         * 通过流的形式实现在jsp上面显示二维码	
         * @param model	
         * @param request	
         * @param response	
         * @throws IOException	
         */	
        @RequestMapping("/readImage")	
        public void readImage(Model model, HttpServletRequest request, HttpServletResponse response) throws IOException{	
            BuildQRCode bc = new BuildQRCode();//调用无参构造方法	
            bc.initParam(bc);//对参数进行初始化	
            QRCode.encoderQRCode(bc);//生成二维码	
    	
            String filePath =  bc.getImgPath();	
            File filePic = new File(filePath);	
            if(filePic.exists()){	
               FileInputStream is = new FileInputStream(filePic);	
               int i = is.available(); // 得到文件大小  	
               byte data[] = new byte[i];  	
               is.read(data); // 读数据  	
               is.close();  	
               response.setContentType("image/*"); // 设置返回的文件类型  	
               OutputStream toClient = response.getOutputStream(); // 得到向客户端输出二进制数据的对象  	
               toClient.write(data); // 输出数据  	
               toClient.close();  	
            }	
        }  	
    	
        /**	
         * 预支付接口	
         * @param timeout	
         * @param orderNo	
         * @return	
         */	
        @RequestMapping("/toPay.do")	
        public String toPay(@RequestParam("timeout") String timeout,@RequestParam("orderNo")String orderNo){	
            log.info("开始进行支付");	
            if(StringUtils.isNullOrEmpty(orderNo)||StringUtils.isNullOrEmpty(timeout)){	
                log.info("订单号或者时间超时为空");	
                return "faile";	
            }	
    	
            Calendar ca = Calendar.getInstance();	
            String afterTime = new SimpleDateFormat("yyyyMMddHHmmssSS").format(ca.getTime());	
    	
            if(!afterTime.equals(timeout)){	
                log.info(afterTime+"---->"+timeout);	
                log.info("二维码已失效,请重新支付");	
                return "faile";	
            }	
            /**	
             * ..... 这段可以根据二维码参数不一样,去相关支付平台进行支付,	
             * 具体代码可以根据支付平台的api文档进行支付操作	
             */	
            log.info("支付成功");	
            return "success";	
        }	
    }

    7.二维码相关参数初始化(我目前二维码存放在本地,你们可以把二维码放在程序目录下)。

    package com.nbt.util;	
    	
    import java.text.SimpleDateFormat;	
    import java.util.Calendar;	
    import java.util.Date;	
    	
    	
    public class BuildQRCode {	
    	
        /**	
         * 二维码存放地址	
         */	
        private   String imgPath ;	
    	
        /**	
         * 二维码内容	
         */	
        private  String content ;	
    	
        /**	
         * 无参构造方法	
         */	
        public BuildQRCode() {	
    	
        }	
    	
    	
        /**	
         * 有参构造方法	
         * @param imgPath	
         * @param content	
         */	
        public BuildQRCode(String imgPath, String content) {	
            super();	
            this.imgPath = imgPath;	
            this.content = content;	
        }	
    	
    	
    	
        public void initParam(BuildQRCode bqrc){	
    	
        //  生成临时订单号和有效时间	
            Calendar ca = Calendar.getInstance();	
            Date date  = ca.getTime();	
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");	
            System.out.println(sdf.format(date));	
            String orderNo = sdf.format(date)+(int)Math.random()*1000;//生成订单号	
            //生成有效时间五分钟	
            ca.add(Calendar.MINUTE,5);	
            System.out.println(sdf.format(ca.getTime()));	
            String timeout = sdf.format(ca.getTime());	
    	
        //对参数进行初始化	
            bqrc.setImgPath( "D:/test/Michael_QRCode.png");	
            bqrc.setContent( "http://localhost:8080/nbt-qrcode/qr/toPay.do?orderNo="+orderNo+"&timeout="+timeout);	
        }	
    	
        public static void main(String[] args) {	
            BuildQRCode qc = new BuildQRCode();	
            qc.initParam(qc);//设置参数	
            QRCode.encoderQRCode(qc);	
        }	
    	
    	
    	
        public  String getImgPath() {	
            return imgPath;	
        }	
    	
        public  void setImgPath(String imgPath) {	
            this.imgPath = imgPath;	
        }	
    	
        public  String getContent() {	
            return content;	
        }	
    	
        public  void setContent(String content) {	
            this.content = content;	
        }	
    }

    福利推荐阅读:

    全栈打卡福利 100%能获得奖品(附新增音频功能)

    周末福利准时到!

    推荐几个我置顶的公众号!

    转载:https://www.cnblogs.com/jpfss/p/9443570.html

    注:

    去今天第二篇文章留言打卡,这篇没有留言功能,(第二篇文章是8年程序员跳槽...),留言打卡第14天。

    觉得本文对你有帮助?请分享给更多人

    关注「全栈开发者社区」加星标,提升全栈技能


    本公众号会不定期给大家发福利,包括送书、学习资源等,敬请期待吧!

    如果感觉推送内容不错,不妨右下角点个在看转发朋友圈或收藏,感谢支持。


    好文章,我在看❤️

    展开全文
  • 中国银联全渠道支付平台--银联二维码支付之主扫、被扫、查询接口
  • 微信公众平台二维码支付

    微信公众平台二维码支付

    生成的二维码主要是用于PC端H5付款的调用,思路是前端调取获取订单接口,目的是前后端校对价格,代码就不予展示
    然后就是根据订单号和价格生成二维码

       @ApiOperation(value = "微信生成二维码", httpMethod = "POST", response = ResultJsonBean.class, notes = "")
        @RequestMapping(value = "/qrcode",  method = {RequestMethod.POST,RequestMethod.GET})
        @ResponseBody
        @ParentPCUser
        public void qrcode(
                @ApiParam(value="token")@RequestParam(required = false) String token,
                @ApiParam(value="支付金额",required = true)@RequestParam(required = true) Long totalprice,
                @ApiParam(value="支付订单号",required = true)@RequestParam(required = true) String orderNo,
                HttpServletRequest request,HttpServletResponse response) {
            try {
                String text = PatriarchWexinPayUtil.weixinPay(orderNo, totalprice*100);
                //根据url来生成生成二维码
                int width = 300;
                int height = 300;
                //二维码的图片格式
                String format = "gif";
                Hashtable hints = new Hashtable();
                //内容所使用编码
                hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
                BitMatrix bitMatrix;
                try {
                    bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
                    MatrixToImageWriter.writeToStream(bitMatrix, format, response.getOutputStream());
                } catch (WriterException e) {
                    e.printStackTrace();
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    然后就是获取code_url工具类

    package com.kyd.util.pay;
    
    import com.alibaba.fastjson.JSONArray;
    import com.kyd.app_parent.service.vo.WeixinPayVO;
    import com.kyd.refund.weixin.util.XmlUtil;
    import com.kyd.util.AppException;
    import com.kyd.util.Base64Util;
    import com.kyd.util.XMLUtil;
    import com.swetake.util.Qrcode;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.HttpStatus;
    import org.apache.commons.httpclient.methods.PostMethod;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.jdom.JDOMException;
    import org.springframework.context.EnvironmentAware;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    import org.springframework.web.client.RestTemplate;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.Security;
    import java.util.Map;
    import java.util.SortedMap;
    import java.util.TreeMap;
    import java.util.UUID;
    
    //import com.swetake.util.Qrcode;
    
    /**
     * 验证是否是微信官网的信息(家长端)
     * @author litao
     *
     */
    @Slf4j
    @Configuration
    public class PatriarchWexinPayUtil implements EnvironmentAware{
    
    
    	public static String AUTH_API = "https://api.weixin.qq.com/sns/oauth2/access_token";
    
    	// 构造签名的map
        // 构造向微信发送参数的实体类
    	
    	/*支付宝合作者身份ID*/
    	private static  String MCH_ID;
    	/*接口名称*/
    //	private static final String APPID=AppEnv.getInstance().getStringProp("weixin.appid", "wx998423eb9b2d522a");
    	private static  String APPID;//智慧校园的微信appid
    	/*接口名称*/
    	private static  String QUERY_URL;
    	private static  String PAY_URL;
    	private static final String KEY="JiaXiaoGongXiangParents0701LoveU";
    	private static String NOTIFY_URL=null;
    	private static String appSecret;
    	@SuppressWarnings("unused")
    	private static  String OPENID;
    	@SuppressWarnings("unused")
    	private static  String SPBILL_CREATE_IP;
    	
    	private static Environment env;
    
    	/**
    	 * 密钥算法
    	 */
    	private static final String ALGORITHM = "AES";
    	/**
    	 * 加解密算法/工作模式/填充方式
    	 */
    	private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";
    
    	public static String getMchId() {
    		return MCH_ID;
    	}
    
    	public static String getNotifyPrefix(){
    		return NOTIFY_URL.substring(0, NOTIFY_URL.lastIndexOf("/"));
    	}
    
    
    
    
    
        public static String decodeReqInfo(String req_info) throws Exception {
    		//1.对加密串A做base64解码,得到加密串B
    		log.info("~~~~~~~~~~~~~进入decodeReqInfo方法");
    		byte[] req_bytes = Base64Util.decode(req_info);
    		log.info("~~~~~~~~~~~~~byte[] req_bytes");
    		//2.对商户key做md5,得到32位小写key*
    		SecretKeySpec key = new SecretKeySpec(MD5Util.MD5Encode(KEY, "UTF-8").toLowerCase().getBytes(), ALGORITHM);
    		log.info("~~~~~~~~~~~~~SecretKeySpec");
    		//3.用key*对加密串B做AES-256-ECB解密
    		Security.addProvider(new BouncyCastleProvider());
    		log.info("~~~~~~~~~~~~~addProvider");
    		// 创建密码器
    		Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING,"BC");
    		log.info("~~~~~~~~~~~~~Cipher");
    		//使用密钥初始化,设置为解密模式
    		cipher.init(Cipher.DECRYPT_MODE, key);
    		log.info("~~~~~~~~~~~~~init");
    		byte[] result = cipher.doFinal(req_bytes);
    		log.info("~~~~~~~~~~~~~result");
    		return new String(result, "utf-8");
    	}
    
        @Override
    	public void setEnvironment(final Environment environment) {
    		this.env = environment;
    		MCH_ID=env.getProperty("weixin.patriarch.mch_id");
    		APPID=env.getProperty("weixin.patriarch.appid");
    		QUERY_URL=env.getProperty("weixin.queryurl");
    		PAY_URL=env.getProperty("weixin.payurl");
    		OPENID=env.getProperty("weixin.openid");
    		SPBILL_CREATE_IP=env.getProperty("weixin.spbill_create_ip");
    		NOTIFY_URL=env.getProperty("weixin.patriarch.notify_url");
    		appSecret=env.getProperty("weixin.patriarch.appSecret");
    	}
    
        
    	/**
    	 *@Description: 生成二维码支付
    	 *@parm  
    	 *@return  
    	 *@Author    litao
    	 *@time  2019/10/22 17:14
    	 *@other
    	 */
    	public static String weixinPay(String orderno, Long totalprice) throws Exception {
    
    		String out_trade_no = orderno; //订单号 (调整为自己的生产逻辑)
    		String nonceStr=UUID.randomUUID().toString().replace("-", "");
    		// 回调接口
    		String trade_type = "NATIVE";
    
    		SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
    		packageParams.put("appid", APPID);
    		packageParams.put("mch_id", MCH_ID);
    		packageParams.put("nonce_str", nonceStr);
    		packageParams.put("body", "\u4ebf\u8d77\u70b9\u7535\u5b50\u4ea7\u54c1");  //(调整为自己的名称)
    		packageParams.put("out_trade_no", out_trade_no);
    		packageParams.put("total_fee", totalprice+""); //价格的单位为分
    		packageParams.put("spbill_create_ip", SPBILL_CREATE_IP);
    		packageParams.put("notify_url", NOTIFY_URL);
    		packageParams.put("trade_type", trade_type);
    //		String sign = WXSignUtils.createSign("UTF-8", packageParams);
    		String sign = PayToolUtil.createSign("UTF-8", packageParams,weixinConstant.KEY);
    		packageParams.put("sign", sign);
    		String requestXML = PayToolUtil.getRequestXml(packageParams);
    		System.out.println(requestXML);
    
    		String resXml = HttpUtil.postData(PAY_URL, requestXML);
    		Map map = XMLUtil4jdom.doXMLParse(resXml);
    		String urlCode = (String) map.get("code_url");
    		return urlCode;
    	}
    
    }
    

    PayToolUtil方法

    package com.kyd.util.pay;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    import java.util.SortedMap;
    
    public class PayToolUtil {
    
        /**
         * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
         * @return boolean
         */
        public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
            StringBuffer sb = new StringBuffer();
            Set es = packageParams.entrySet();
            Iterator it = es.iterator();
            while(it.hasNext()) {
                Map.Entry entry = (Map.Entry)it.next();
                String k = (String)entry.getKey();
                String v = (String)entry.getValue();
                if(!"sign".equals(k) && null != v && !"".equals(v)) {
                    sb.append(k + "=" + v + "&");
                }
            }
    
            sb.append("key=" + API_KEY);
    
            //算出摘要
            String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();
            String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();
    
            //System.out.println(tenpaySign + "    " + mysign);
            return tenpaySign.equals(mysign);
        }
    
        /**
         * @author
         * @date 2016-4-22
         * @Description:sign签名
         * @param characterEncoding
         *            编码格式
         * @param parameters
         *            请求参数
         * @return
         */
        public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
            StringBuffer sb = new StringBuffer();
            Set es = packageParams.entrySet();
            Iterator it = es.iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                String k = (String) entry.getKey();
                String v = (String) entry.getValue();
                if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                    sb.append(k + "=" + v + "&");
                }
            }
            sb.append("key=" + API_KEY);
            String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
            return sign;
        }
    
        /**
         * @author
         * @date 2016-4-22
         * @Description:将请求参数转换为xml格式的string
         * @param parameters
         *            请求参数
         * @return
         */
        public static String getRequestXml(SortedMap<Object, Object> parameters) {
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");
            Set es = parameters.entrySet();
            Iterator it = es.iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                String k = (String) entry.getKey();
                String v = (String) entry.getValue();
                if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
                    sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
                } else {
                    sb.append("<" + k + ">" + v + "</" + k + ">");
                }
            }
            sb.append("</xml>");
            return sb.toString();
        }
    
        /**
         * 取出一个指定长度大小的随机正整数.
         *
         * @param length
         *            int 设定所取出随机数的长度。length小于11
         * @return int 返回生成的随机数。
         */
        public static int buildRandom(int length) {
            int num = 1;
            double random = Math.random();
            if (random < 0.1) {
                random = random + 0.1;
            }
            for (int i = 0; i < length; i++) {
                num = num * 10;
            }
            return (int) ((random * num));
        }
    
        /**
         * 获取当前时间 yyyyMMddHHmmss
         *
         * @return String
         */
        public static String getCurrTime() {
            Date now = new Date();
            SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            String s = outFormat.format(now);
            return s;
        }
    }
    

    http工具类,负责发起post请求并获取的返回

    package com.kyd.util.pay;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.URL;
    import java.net.URLConnection;
    
    /**
     * http工具类,负责发起post请求并获取的返回
     */
    public class HttpUtil {
        private final static int CONNECT_TIMEOUT = 5000; // in milliseconds
        private final static String DEFAULT_ENCODING = "UTF-8";
    
        public static String postData(String urlStr, String data){
            return postData(urlStr, data, null);
        }
    
        public static String postData(String urlStr, String data, String contentType){
            BufferedReader reader = null;
            try {
                URL url = new URL(urlStr);
                URLConnection conn = url.openConnection();
                conn.setDoOutput(true);
                conn.setConnectTimeout(CONNECT_TIMEOUT);
                conn.setReadTimeout(CONNECT_TIMEOUT);
                if(contentType != null)
                    conn.setRequestProperty("content-type", contentType);
                OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
                if(data == null)
                    data = "";
                writer.write(data);
                writer.flush();
                writer.close();
    
                reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                    sb.append("\r\n");
                }
                return sb.toString();
            } catch (IOException e) {
                //logger.error("Error connecting to " + urlStr + ": " + e.getMessage());
            } finally {
                try {
                    if (reader != null)
                        reader.close();
                } catch (IOException e) {
                }
            }
            return null;
        }
    }
    

    然后就是生成二维码的工具类

    package com.kyd.util.pay;
    
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.io.OutputStream;
    import javax.imageio.ImageIO;
    import com.google.zxing.common.BitMatrix;
    public class MatrixToImageWriter {
    
        private static final int BLACK = 0xFF000000;
    
        private static final int WHITE = 0xFFFFFFFF;
    
        private MatrixToImageWriter() {
        }
    
        public static BufferedImage toBufferedImage(BitMatrix matrix) {
    
            int width = matrix.getWidth();
    
            int height = matrix.getHeight();
    
            BufferedImage image = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
                }
            }
            return image;
        }
    
        public static void writeToFile(BitMatrix matrix, String format, File file)
    
                throws IOException {
            BufferedImage image = toBufferedImage(matrix);
            if (!ImageIO.write(image, format, file)) {
                throw new IOException("Could not write an image of format "
                        + format + " to " + file);
            }
        }
    
        public static void writeToStream(BitMatrix matrix, String format,
                                         OutputStream stream)
                throws IOException {
            BufferedImage image = toBufferedImage(matrix);
            if (!ImageIO.write(image, format, stream)) {
                throw new IOException("Could not write an image of format "
                        + format);
            }
        }
    }
    

    按照整体流程前端请求就会生成一个直接可以扫描付款的二维码
    生成的二维码
    扫码结果
    在这里插入图片描述

    展开全文
  • ③自定义二维码扫码支付 参数配置-开放平台相关配置(沙箱环境) 刚开始支付宝的配置参数还是有点让人懵逼的,跟微信支付有点不同,支付宝有个沙箱测试环境,跟正式环境差不多,不过正式环境还需要签约审核,没...
  • 首先申明,本人实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是spring springmvc mybatis 框架,maven管理。其实如果支付,不需要mybatis也能实现,代码和本人见解还...
  • 二维码支付的优势与劣势

    千次阅读 2019-09-20 14:41:33
     第三方移动支付是指交易双方通过手机、平扳电脑等移动终端,利用移动通信网络和无线通信技术,由独立于移动通讯运营商与银行以外的第三方支付平台支持的支付服务,完成资金转移及支付的行为。    2.二维码支付...
  • php支付宝二维码支付

    千次阅读 2019-04-07 14:51:57
    <?php header('Content-type:text/html; Charset=utf-8'); /*** 请填写以下配置信息 ***/ $appid = '*******';...密钥管理->开放平台密钥,填写添加了电脑网站支付的应用的APPID $notifyUrl = '*******'; /...
  • python支付宝支付 微信、支付宝二维码聚合SDK下载 点我下载 1、沙箱环境配置 在支付宝提供的沙箱环境中进行开发,用自己的支付宝账号去申请一个沙箱账号。 可以参考沙箱使用说明获取AppID等,然后根据说明下载安卓...
  • 最近在工作上看到一个奇葩问题,在Android和Windows平台上做请求时参数都可以正常传递和接收,但在IOS系统下,微信自带页面进行二维码支付页面跳转的时候,参数无法带过去,导致页面报错。需要将 form属性中的target ...
  • 首先申明,本人实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是spring springmvc mybatis 框架,maven管理。其实如果支付,不需要mybatis也能实现,代码和本人见解还...
  • php实现支付宝二维码支付

    千次阅读 2019-04-06 21:46:15
    下面是代码 <?php header('Content-type:text... Charset=utf-8'); /*** 请填写以下配置信息 ***/ $appid = '*******';...密钥管理->开放平台密钥,填写添加了电脑网站支付的应用的APPID $notifyUrl = '*******';...
  • 1、此文档为中国银联全渠道支付平台-产品接口规范-商户卷-第16部分 二维码支付的接口规范 2、对做金融POS产品开发,特别是扫码POS开发有一定的参考意义
  • Python实现支付宝二维码支付(沙箱环境)

    千次阅读 热门讨论 2019-06-22 23:49:47
    Python实现支付宝二维码支付 一.沙箱环境配置 1.登陆蚂蚁金融开放平台:https://openhome.alipay.com 2.选择进入我的开放平台。寻找开发中心的研发服务。 3.点击沙箱环境—沙箱应用 4.这里博主已经配置好...
  • 对接微信二维码支付(native方式)

    万次阅读 2019-07-11 16:34:12
    微信对接分多中方式,而native是调用微信支付服务在网页生成二维码,客户扫描二维码支付。 2.准备工作 (1)申请服务号,需要审核认证,300块钱。 (2)服务号申请通过后,在微信公众平台开通微信支付 开通...
  • SpringBoot集成微信支付(二维码支付

    千次阅读 热门讨论 2020-06-06 21:07:53
    申请完成后需要等待 1-3 天审核,审核通过后需要在 微信商户平台 获取 appID(公众号ID),mchID (商户ID)、key (在微信支付中设置的私钥)、安全证书 二、在springboot整合微信支付 1. 导入所需的依赖 <!-- ...
  • java实现支付宝二维码支付(Spring Boot)

    千次阅读 2019-10-29 15:12:09
    首先集成alipay的sdk,然后要到支付宝商户平台创建应用,生成私钥 公钥, 话不多说直接上代码块 @ApiOperation(value = "支付宝生成二维码", httpMethod = "POST", response = ResultJsonBean.class, notes = "") ...
  • 适用于:各行各业(如,超市 餐厅 收费站 等各类收费处)       平台管理员篇 ...(支付宝二维码支付)     商家篇 我的扫码付 (支付宝二维码支付) 收款账号管理
  • 支付宝PC端二维码支付(沙箱环境)

    千次阅读 2018-11-27 16:20:45
    支付宝开放平台: https://openhome.alipay.com/platform/developerIndex.htm 在这里根据规则设置私钥和公钥 下面有一个钱包下载二维码,下载沙箱钱包后,查看账号密码并登录买家账号 二,配置文件 将...
  • 实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是 spring springmvc mybatis 框架, maven 管理。 其实如果支付,不需要 mybatis 也能实现,代码和本人见解还需大神...
  • 工行二维码支付接口及回调接口

    千次阅读 2019-09-29 11:11:40
    工行的接口文档详见工行开放平台地址 ... * 获取支付二维码 * * @param outTradeNo * @param orderAmt * @param attach * @param notifyUrl * @return */ public static JSONObject ge...
  • 相对于第四方支付来说,第三方支付平台的业务范畴更广泛,而第四方支付平台的业务一般来说比较单一,在支付某个领域更加专注,比如支付FM就是第四方聚合支付平台,是专注于聚合二维码收款和签约接口收款系统的第四方...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 709
精华内容 283
关键字:

二维码支付平台