ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

支付宝的当面付扫一扫功能

2021-06-08 09:57:20  阅读:316  来源: 互联网

标签:付扫 String 支付宝 一扫 import mmall com order


首先需要一个沙箱环境,专门为开发者提供的。里面给你提供了卖家账号,和买家账号。具体的自行百度。
需要下载沙箱版的支付宝,然后登陆提供的买卖家账号即可操作。因为在沙箱环境中支付宝给出的二维码只能在沙箱版的支付宝中扫。
沙箱买卖家:
https://openhome.alipay.com/platform/appDaily.htm?tab=account
沙箱需要的配置文件信息:
https://openhome.alipay.com/platform/appDaily.htm?tab=info
当面付demo
https://docs.open.alipay.com/54/104506/
需要一个sra2秘钥生成器,支付宝有提供下载:
https://openclub.alipay.com/read.php?tid=955&fid=46
支付宝当面付开发者文档
https://docs.open.alipay.com/194

场景:用户下单,然后我们后台会去掉支付宝的接口,当然支付宝接口需要一些参数,比如说,标题了,订单号,总金额,物品明细,等等之类的,这些支付宝官方的demo中都有,直接拿过来改造就行。我们主要的是掉支付宝的接口让他给我们返回一个json串,里面有个网址,生成二维码的。然后我们再用这个一个工具包将这个二维码生成二维码,保存到我们的图片服务器上。然后,我们用刚刚下载好的沙箱支付宝扫码支付。然后,支付成功,支付宝会会回调我们之前设置的本地的回调函数(内网映射)。参数中有支付宝返回的结果,比如订单号,支付状态,支付时间等等,但是这些都时支付宝给我们的一些结果,在这之前,我们必须要验证一下这个回调函数是不是支付宝发起的,支付包的demo里有提供这个方法,返回的是布尔值。然后是true的时候,进行我们下一步的操作,就是验证返回的结果的参数正确性和更该数据库里面的状态。最后如果支付成功,给支付宝返回success,不然,支付宝会隔一段时间还回调,具体看文档。大致流程就是这样的。不会的给我留言。。。。

controller

package com.mmall.controller.protal;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.demo.trade.config.Configs;
import com.google.common.collect.Maps;
import com.mmall.common.Const;
import com.mmall.common.ServerResponse;
import com.mmall.dao.OrderMapper;
import com.mmall.pojo.Order;
import com.mmall.pojo.User;
import com.mmall.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by 敲代码的卡卡罗特
 * on 2018/3/18 14:08.
 */
@RequestMapping("/order/")
@Controller
@Slf4j
public class OrderController {
    @Autowired
    IOrderService iOrderService;
    @RequestMapping("pay.do")
    @ResponseBody
    public ServerResponse pay(HttpSession httpSession, Long orderNo, HttpServletRequest request){
        User user = (User)httpSession.getAttribute(Const.CURRENT_USER);
        if (user==null){
            return ServerResponse.createByError("请登录账号");
        }
        System.out.println("request.getContextPath():----"+request.getContextPath());
        System.out.println("request.getSession().getServletContext()-----"+request.getSession().getServletContext().getRealPath("upload"));
        String upload = request.getSession().getServletContext().getRealPath("upload");
        return  iOrderService.pay(orderNo,user.getId(),upload);
    }
    @RequestMapping("alipay_callback.do")
    @ResponseBody
    public Object alipayCallback(HttpServletRequest httpServlet){
        HashMap<String, String> map = Maps.newHashMap();
        Map<String, String[]> parameterMap = httpServlet.getParameterMap();
        Set<String> set = parameterMap.keySet();
        for (String s: set){
            String[] strings = parameterMap.get(s);
            String str="";
            for (int i=0;i<strings.length;i++){
                str=i==strings.length-1?str+strings[i]:str+strings[i]+",";
            }
            map.put(s,str);
        }
        log.info("支付宝回调:sign:{},trade_status:{},参数:{}",map.get("sign"),map.get("trade_status"),map.toString());

        //验签是不是支付宝发起的回调
        map.remove("sign_type");
        try {
            Configs.init("zfbinfo.properties");
            boolean bool = AlipaySignature.rsaCheckV2(map, Configs.getAlipayPublicKey(), "utf-8", Configs.getSignType());
            if (!bool){
                return ServerResponse.createByError("非法请求,再请求老子就报警了");
            }

        } catch (AlipayApiException e) {
            log.error("支付宝验证回调异常",e);
        }
        ServerResponse alipaycall = iOrderService.alipaycall(map);
        if (alipaycall.isSuccess()){
            return Const.AlipayCallback.RESPONSE_SUCCESS;
        }
        return Const.AlipayCallback.RESPONSE_FAILED;
    }


    @RequestMapping("queryOrderPayStatus.do")
    @ResponseBody
    public ServerResponse queryOrderPayStatus(HttpSession httpSession, Long orderNo){
        User user = (User)httpSession.getAttribute(Const.CURRENT_USER);
        if (user==null){
            return ServerResponse.createByError("请登录账号");
        }
        ServerResponse serverResponse = iOrderService.queryOrderPayStatus(user.getId(), orderNo);
        if (serverResponse.isSuccess()){
            return ServerResponse.createBySuccess(true);
        }
        return  ServerResponse.createBySuccess(false);
    }
}

service

package com.mmall.service.impl;

import com.alipay.api.AlipayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
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.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mmall.common.Const;
import com.mmall.common.ServerResponse;
import com.mmall.dao.OrderItemMapper;
import com.mmall.dao.OrderMapper;
import com.mmall.dao.PayInfoMapper;
import com.mmall.pojo.Order;
import com.mmall.pojo.OrderItem;
import com.mmall.pojo.PayInfo;
import com.mmall.service.IOrderService;
import com.mmall.untis.BigDecimalUtil;
import com.mmall.untis.DateUtils;
import com.mmall.untis.FTPUtil;
import com.mmall.untis.PropertiesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 敲代码的卡卡罗特
 * on 2018/3/18 14:17.
 */
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    OrderItemMapper orderItemMapper;

    @Autowired
    PayInfoMapper payInfoMapper;
    // 支付宝当面付2.0服务
    private static AlipayTradeService tradeService;
    public ServerResponse pay(Long orderNo,Integer userId,String path){
        HashMap map = Maps.newHashMap();
        if (orderNo==null){
            return  ServerResponse.createByError("参数错误");
        }
        Order order = orderMapper.selectByUserIdAndOrderNo(userId, orderNo);
        if (order==null){
            return  ServerResponse.createByError("没有查到该订单");
        }
        map.put("orderNo",order.getOrderNo());
        // (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线,
        // 需保证商户系统端不能重复,建议通过数据库sequence生成,
        String outTradeNo = order.getOrderNo().toString();

        // (必填) 订单标题,粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = new StringBuilder().append("快乐慕商城订单:").append(outTradeNo).append("生成订单成功").toString();

        // (必填) 订单总金额,单位为元,不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = order.getPayment().toString();

        // (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0";

        // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)
        // 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID
        String sellerId = "";

        // 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"
        String body = new StringBuilder().append("订单:").append(outTradeNo).append(",购买商品共:").append(totalAmount).toString();

        // 商户操作员编号,添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
        String storeId = "test_store_id";

        // 业务扩展参数,目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法),详情请咨询支付宝技术支持
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId("2088100200300400500");

        // 支付超时,定义为120分钟
        String timeoutExpress = "120m";

        // 商品明细列表,需填写购买商品详细信息,
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        List<OrderItem> orderItems = orderItemMapper.getOrderItemByUserIdAndOrderNo(userId, order.getOrderNo());
        for (OrderItem orderItem : orderItems){
            GoodsDetail goods1 = GoodsDetail.newInstance(orderItem.getProductId().toString(),
                    orderItem.getProductName(),
                    BigDecimalUtil.mul(orderItem.getCurrentUnitPrice().doubleValue(),orderItem.getQuantity()).longValue(),
                    orderItem.getQuantity());
            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(PropertiesUtil.getProperty("alipay.callback.url"))//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
                .setGoodsDetailList(goodsDetailList);
        /** 一定要在创建AlipayTradeService之前调用Configs.init()设置默认参数
         *  Configs会读取classpath下的zfbinfo.properties文件配置信息,如果找不到该文件则确认该文件是否在classpath目录
         */
        Configs.init("zfbinfo.properties");

        /** 使用Configs提供的默认参数
         *  AlipayTradeService可以使用单例或者为静态成员对象,不需要反复new
         */
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝预下单成功: )");

                AlipayTradePrecreateResponse response = result.getResponse();
                dumpResponse(response);
                File folder = new File(path);
                if (!folder.exists()){
                    folder.setWritable(true);
                    folder.mkdirs();
                }
                // 需要修改为运行机器上的路径
                String qrPath = String.format(path+"/qr-%s.png",
                        response.getOutTradeNo());
                String qrFileName = String.format("qr-%s.png",
                        response.getOutTradeNo());
                ZxingUtils.getQRCodeImge(response.getQrCode(),256,qrPath);
                File targetFile = new File(path, qrFileName);
                try {
                    FTPUtil.uploadFile(Lists.newArrayList(targetFile));
                } catch (IOException e) {
                    log.error("上传到ftp服务器的二维码异常");
                    e.printStackTrace();
                }
                log.info("filePath:" + qrPath);
                String qrurl= PropertiesUtil.getProperty("ftp.server.http.prefix")+targetFile.getName();
                map.put("qrurl",qrurl);
                return ServerResponse.createBySuccess(map);
            case FAILED:
                log.error("支付宝预下单失败!!!");
                return ServerResponse.createByError("支付宝预下单失败!!!");
            case UNKNOWN:
                log.error("系统异常,预下单状态未知!!!");
                return ServerResponse.createByError("系统异常,预下单状态未知!!!");
            default:
                log.error("不支持的交易状态,交易返回异常!!!");
                return ServerResponse.createByError("不支持的交易状态,交易返回异常!!!");
        }
    }

    // 简单打印应答
    private 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());
        }
    }


    public ServerResponse alipaycall(Map<String,String> map){
        Long out_trade_no = Long.valueOf(map.get("out_trade_no"));
        String trade_no = map.get("trade_no");
        String trade_status = map.get("trade_status");
        Order order = orderMapper.selectByOrderNo(out_trade_no);
        if (order==null){
            return ServerResponse.createByError("非快乐慕商城的订单,请忽略");
        }
        if (order.getStatus()>=Const.order.PAID.getCode()){
            return ServerResponse.createBySuccess("支付宝重复调用");
        }
        if (Const.AlipayCallback.TRADE_STATUS_TRADE_SUCCESS.equals(trade_status)){
            order.setStatus(Const.order.PAID.getCode());
            order.setPaymentTime(DateUtils.strToDate(map.get("gmt_create")));
            orderMapper.updateByPrimaryKey(order);
        }
        PayInfo payInfo = new PayInfo();
        payInfo.setUserId(order.getUserId());
        payInfo.setOrderNo(order.getOrderNo());
        payInfo.setPayPlatform(Const.PayPlatformEnum.ALI.getCode());
        payInfo.setPlatformNumber(trade_no);
        payInfo.setPlatformStatus(trade_status);

        payInfoMapper.insert(payInfo);
        return ServerResponse.createBySuccess();
    }

    public ServerResponse queryOrderPayStatus(Integer userId,Long orderNo){
        Order order = orderMapper.selectByUserIdAndOrderNo(userId, orderNo);
        if (order==null){
            return ServerResponse.createByError("没有该订单");
        }

        if (order.getStatus()>=Const.order.PAID.getCode()){
            return ServerResponse.createBySuccess(true);
        }
        return ServerResponse.createBySuccess(false);
    }
}

标签:付扫,String,支付宝,一扫,import,mmall,com,order
来源: https://blog.51cto.com/u_12784254/2880203

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有