首页 > 分享 > AliPay

AliPay

一、前言

AliPay - Java支付宝接口开发(一)

AliPay - Java支付宝接口开发(二)

二、支付宝沙箱环境集成Web项目

1、将支付宝Demo中的相关文件复制到我们的项目中

1.1 Maven以外的Jar包(红框部分)(主要2个,还有2个是对应的源码)

1.2 Maven以内的Jar包(最好版本号都一样,以免出现意想不到的事)

<dependencies>

<dependency>

<groupId>commons-codec</groupId>

<artifactId>commons-codec</artifactId>

<version>1.10</version>

</dependency>

<dependency>

<groupId>commons-configuration</groupId>

<artifactId>commons-configuration</artifactId>

<version>1.10</version>

</dependency>

<dependency>

<groupId>commons-lang</groupId>

<artifactId>commons-lang</artifactId>

<version>2.6</version>

</dependency>

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.1</version>

</dependency>

<dependency>

<groupId>com.google.zxing</groupId>

<artifactId>core</artifactId>

<version>2.1</version>

</dependency>

<dependency>

<groupId>com.google.code.gson</groupId>

<artifactId>gson</artifactId>

<version>2.3.1</version>

</dependency>

<dependency>

<groupId>org.hamcrest</groupId>

<artifactId>hamcrest-core</artifactId>

<version>1.3</version>

</dependency>

</dependencies>

1.3 上面是jar包的配置,接下来我们在pom.xml里面配置一个插件,使项目编译需要的jar在项目部署的时候自动将 lib 包里的Jar添加到项目依赖中

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<configuration>

<source>1.7</source>

<target>1.7</target>

<encoding>UTF-8</encoding>

<compilerArguments>

<extdirs>${project.basedir}/src/main/webapp/WEB-INF/lib</extdirs>

</compilerArguments>

</configuration>

</plugin>

1.4 zhifubao.properties这个配置文件方法我们项目中的 resources目录下

open_api_domain = https://openapi.alipaydev.com/gateway.do

mcloud_api_domain = http://mcloudmonitor.com/gateway.do

pid = 2088102180444972

appid = 2016102100728313

private_key = MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCKQ2pEIzXM4IoN1cMzOFXdlk8yVX2cKXWITZ92EGAQQcRytaV07yQOaz3UE9KTeT9Nu628G+HZMsJUxQjEUETagmY5nLtbeL35M2UcibYpM3e2gVTtUW86CA65GCdLzUhdIug8yf2F9zWayzG4sHZ9DcTezG6ZjFu+EtDpFgg+CtqY7n/ihjTIqeE1lX0C2ZIKpIYs7QjR8AztB/qRcpOJKRfMKGDgmT9GALN8LeFEYCbQ+W/GJHN8bQ0Bk1Ll6EKQ4cHXZ1Yko+aXaRfbXfUZYgD9hwAVlxtwZndgeFX8KapOCw0J25pzV4WkutIjMlt7I2Q1jaWNoKLuxtz4M2mzAgMBAAECggEAAhnsL4TpeGehMXyiLtEYXPm/0mACPLFUm/GyDrVJAHY/ag7gqNpJjf6LPgHfHWamU6Qai9VQpWBkG62y6Gjf4wJAU3fSUR2QpYzmaHyfTBkAJMHqbIDkU9lzf9SiJEDGbMPvC512QOb05ZlY9Bmac2QWLdylgafkbQsUKbawAWFa/BAOMIp0tgYLW8/yY2aG6jeLqhOgTo8MWIW5d1qHtX5m/x7g97dYYMdX3kTo2i1dFLUVfEOvZe4US6VBvLg71dMxwadVF5YMaY9jq/ShPD0Gkf29wdThwsjcH6u9Tq/KArQTK+z02DAGkdWOcue3pHql+gvoIA8U5uFDdIeYwQKBgQDri3jPkDKi48efdKQk38rn+CJYeNFNRAhlly3h2AHaFEY92XRlBsho/vGFg43BvHu+cMz0Run4SS8Vo09vcTIY6p2xNMffjR0w2gQqx6PUdGHBFtw7FavxN4uVtVhL6uTAqfBv97mqQO0bq+DhOGwSRNIWqvnzfXywqwmXhKYECwKBgQCWRTl6tNv8scxPq4fpRL/uw71TU6XqSS/nME7KT4uyQPAXPk0mXVVwdmyST9Crlr6O6WJopPe9nMIFUYdjdkLfGKLCR96AH3U7frr4jf60eDYEhfHGIzln/ptrTJLvvbXTaPctAaZd6TIv63QVz3yim4MMl3VSdRlrE+O9R5ZR+QKBgQDjEP8TyUSnNsJX+4/JZFwsp04kz8OlorIdjVHT5/JREz5rnVfRlGpanXqjZSCg5Vy9R+ysiDhA+/wB9f87xXmv/2ypSeJspZLAZ0uhGffbdZ5PEASaiNfKn+tWFQ3bkcOX37tDlSJM+G4bQOR2+XdlXSbSZ1yx2AT+IsQKZvvL5QKBgQCPZEUiEz0sV1kX2R2a+XCQ3RVnUxWqh+X/HPjCUr+B/DdeZqPl7QAfjdGymBkN842o/4lZQ7nnpJL70j14KpxLGM4Ox9fIuLv8ZsTxc0XOXjtle48nO+uGkc0qyWoY/RVpQ+tBdiaTzHeIhIxEV7adz/lwZYKdiYIUzGjv8ES/uQKBgCgeWysXjahCQItxx5fTrS8SQFP7Dx5vDW+UkqQ2pbL0AlHyUS7pWJj3AAe3pn4AJZZp4SZPoQP+Z8JPqDA6MrQWHYMi0XkMuMYwLWbGCkmf1MnjUxgOaLXoItjxS/y3jQfeOmHhmOAVkjnEvAh+BWlZxFMv2kiuHRU72bNa0rDI

public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAikNqRCM1zOCKDdXDMzhV3ZZPMlV9nCl1iE2fdhBgEEHEcrWldO8kDms91BPSk3k/TbutvBvh2TLCVMUIxFBE2oJmOZy7W3i9+TNlHIm2KTN3toFU7VFvOggOuRgnS81IXSLoPMn9hfc1mssxuLB2fQ3E3sxumYxbvhLQ6RYIPgramO5/4oY0yKnhNZV9AtmSCqSGLO0I0fAM7Qf6kXKTiSkXzChg4Jk/RgCzfC3hRGAm0PlvxiRzfG0NAZNS5ehCkOHB12dWJKPml2kX2131GWIA/YcAFZcbcGZ3YHhV/CmqTgsNCduac1eFpLrSIzJbeyNkNY2ljaCi7sbc+DNpswIDAQAB

alipay_public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzWgVL/NWrJAeyEImwtaK3IDwj0dKkqUDIfqqWn5SiLaWMYi9RmKhn+jY9VM7JXEIkYYeVlqIL6Xn7OvYFRTi4buTCXGKvFLn95aDcaur77/S/0ibcdN1K2wIoHzaqQhXAb1ezKxTnFP7OLJsAL22b0NzrQDj2OH9SA06gJb8nHBfR+7Sx7DfwcqE0OtTcDHjbbcB24Qgg/dfItxoEnKuSyRVrf6BtpUnJxSzG/Ge7FfF+VBq8re1t4ZTSxaDEjto071I5VFBxr7I4SyqZsc7WpAmZL8AqUgEbQ1XYBWx2LnpJXM5GQW/thUvcDDqzea7LJNWJOQPM5DaZQgu7QuuwIDAQAB

sign_type = RSA2

max_query_retry = 5

query_duration = 5000

max_cancel_retry = 3

cancel_duration = 2000

heartbeat_delay = 5

heartbeat_duration = 900

1.5 继而我们运行一下复制过来的Main.class,发现Demo是可以跑起来的~

2、编写支付接口

2.1 OrderController类

@Controller

@RequestMapping("/order/")

public class OrderController {

private static final Logger logger = LoggerFactory.getLogger(OrderController.class);

@RequestMapping("pay.do")

@ResponseBody

public ServerResponse pay(HttpSession session, Long orderNo, HttpServletRequest request){

User user = (User)session.getAttribute(Const.CURRENT_USER);

if(user == null){

return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());

}

String path = request.getSession().getServletContext().getRealPath("upload");

return iOrderService.pay(orderNo,user.getId(),path);

}

@RequestMapping("alipay_callback.do")

@ResponseBody

public Object alipayCallback(HttpServletRequest request){

Map<String,String> params = Maps.newHashMap();

Map requestParams = request.getParameterMap();

for(Iterator iter = requestParams.keySet().iterator();iter.hasNext();){

String name = (String)iter.next();

String[] values = (String[]) requestParams.get(name);

String valueStr = "";

for(int i = 0 ; i <values.length;i++){

valueStr = (i == values.length -1)?valueStr + values[i]:valueStr + values[i]+",";

}

params.put(name,valueStr);

}

logger.info("支付宝回调,sign:{},trade_status:{},参数:{}",params.get("sign"),params.get("trade_status"),params.toString());

params.remove("sign_type");

try {

boolean alipayRSACheckedV2 = AlipaySignature.rsaCheckV2(params, Configs.getAlipayPublicKey(),"utf-8",Configs.getSignType());

if(!alipayRSACheckedV2){

return ServerResponse.createByErrorMessage("非法请求,验证不通过,再恶意请求我就报警找网警了");

}

} catch (AlipayApiException e) {

logger.error("支付宝验证回调异常",e);

}

ServerResponse serverResponse = iOrderService.aliCallback(params);

if(serverResponse.isSuccess()){

return Const.AlipayCallback.RESPONSE_SUCCESS;

}

return Const.AlipayCallback.RESPONSE_FAILED;

}

@RequestMapping("query_order_pay_status.do")

@ResponseBody

public ServerResponse<Boolean> queryOrderPayStatus(HttpSession session, Long orderNo){

User user = (User)session.getAttribute(Const.CURRENT_USER);

if(user ==null){

return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());

}

ServerResponse serverResponse = iOrderService.queryOrderPayStatus(user.getId(),orderNo);

if(serverResponse.isSuccess()){

return ServerResponse.createBySuccess(true);

}

return ServerResponse.createBySuccess(false);

}

}

2.2 IOrderService接口类

package com.mmall.service;

import com.github.pagehelper.PageInfo;

import com.mmall.common.ServerResponse;

import com.mmall.vo.OrderVo;

import java.util.Map;

public interface IOrderService {

ServerResponse pay(Long orderNo, Integer userId, String path);

ServerResponse aliCallback(Map<String,String> params);

ServerResponse queryOrderPayStatus(Integer userId,Long orderNo);

}

2.3 OrderServiceImpl实现类

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.github.pagehelper.PageHelper;

import com.github.pagehelper.PageInfo;

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.CartMapper;

import com.mmall.dao.OrderItemMapper;

import com.mmall.dao.OrderMapper;

import com.mmall.dao.PayInfoMapper;

import com.mmall.dao.ProductMapper;

import com.mmall.dao.ShippingMapper;

import com.mmall.pojo.Cart;

import com.mmall.pojo.Order;

import com.mmall.pojo.OrderItem;

import com.mmall.pojo.PayInfo;

import com.mmall.pojo.Product;

import com.mmall.pojo.Shipping;

import com.mmall.service.IOrderService;

import com.mmall.util.BigDecimalUtil;

import com.mmall.util.DateTimeUtil;

import com.mmall.util.FTPUtil;

import com.mmall.util.PropertiesUtil;

import com.mmall.vo.OrderItemVo;

import com.mmall.vo.OrderProductVo;

import com.mmall.vo.OrderVo;

import com.mmall.vo.ShippingVo;

import org.apache.commons.collections.CollectionUtils;

import org.apache.commons.lang.StringUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.io.File;

import java.io.IOException;

import java.math.BigDecimal;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import java.util.Map;

import java.util.Random;

@Service("iOrderService")

public class OrderServiceImpl implements IOrderService {

private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

private static AlipayTradeService tradeService;

static {

Configs.init("zfbinfo.properties");

tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();

}

@Autowired

private OrderMapper orderMapper;

@Autowired

private OrderItemMapper orderItemMapper;

public ServerResponse pay(Long orderNo,Integer userId,String path){

Map<String,String> resultMap = Maps.newHashMap();

Order order = orderMapper.selectByUserIdAndOrderNo(userId,orderNo);

if(order == null){

return ServerResponse.createByErrorMessage("用户没有该订单");

}

resultMap.put("orderNo",String.valueOf(order.getOrderNo()));

String outTradeNo = order.getOrderNo().toString();

String subject = new StringBuilder().append("happymmall扫码支付,订单号:").append(outTradeNo).toString();

String totalAmount = order.getPayment().toString();

String undiscountableAmount = "0";

String sellerId = "";

String body = new StringBuilder().append("订单").append(outTradeNo).append("购买商品共").append(totalAmount).append("元").toString();

String operatorId = "test_operator_id";

String storeId = "test_store_id";

ExtendParams extendParams = new ExtendParams();

extendParams.setSysServiceProviderId("2088100200300400500");

String timeoutExpress = "120m";

List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();

List<OrderItem> orderItemList = orderItemMapper.getByOrderNoUserId(orderNo,userId);

for(OrderItem orderItem : orderItemList){

GoodsDetail goods = GoodsDetail.newInstance(orderItem.getProductId().toString(), orderItem.getProductName(),

BigDecimalUtil.mul(orderItem.getCurrentUnitPrice().doubleValue(),new Double(100).doubleValue()).longValue(),

orderItem.getQuantity());

goodsDetailList.add(goods);

}

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"))

.setGoodsDetailList(goodsDetailList);

AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);

switch (result.getTradeStatus()) {

case SUCCESS:

logger.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) {

logger.error("上传二维码异常",e);

}

logger.info("qrPath:" + qrPath);

String qrUrl = PropertiesUtil.getProperty("ftp.server.http.prefix")+targetFile.getName();

resultMap.put("qrUrl",qrUrl);

return ServerResponse.createBySuccess(resultMap);

case FAILED:

logger.error("支付宝预下单失败!!!");

return ServerResponse.createByErrorMessage("支付宝预下单失败!!!");

case UNKNOWN:

logger.error("系统异常,预下单状态未知!!!");

return ServerResponse.createByErrorMessage("系统异常,预下单状态未知!!!");

default:

logger.error("不支持的交易状态,交易返回异常!!!");

return ServerResponse.createByErrorMessage("不支持的交易状态,交易返回异常!!!");

}

}

private void dumpResponse(AlipayResponse response) {

if (response != null) {

logger.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));

if (StringUtils.isNotEmpty(response.getSubCode())) {

logger.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),

response.getSubMsg()));

}

logger.info("body:" + response.getBody());

}

}

public ServerResponse aliCallback(Map<String,String> params){

Long orderNo = Long.parseLong(params.get("out_trade_no"));

String tradeNo = params.get("trade_no");

String tradeStatus = params.get("trade_status");

Order order = orderMapper.selectByOrderNo(orderNo);

if(order == null){

return ServerResponse.createByErrorMessage("非快乐慕商城的订单,回调忽略");

}

if(order.getStatus() >= Const.OrderStatusEnum.PAID.getCode()){

return ServerResponse.createBySuccess("支付宝重复调用");

}

if(Const.AlipayCallback.TRADE_STATUS_TRADE_SUCCESS.equals(tradeStatus)){

order.setPaymentTime(DateTimeUtil.strToDate(params.get("gmt_payment")));

order.setStatus(Const.OrderStatusEnum.PAID.getCode());

orderMapper.updateByPrimaryKeySelective(order);

}

PayInfo payInfo = new PayInfo();

payInfo.setUserId(order.getUserId());

payInfo.setOrderNo(order.getOrderNo());

payInfo.setPayPlatform(Const.PayPlatformEnum.ALIPAY.getCode());

payInfo.setPlatformNumber(tradeNo);

payInfo.setPlatformStatus(tradeStatus);

payInfoMapper.insert(payInfo);

return ServerResponse.createBySuccess();

}

public ServerResponse queryOrderPayStatus(Integer userId,Long orderNo){

Order order = orderMapper.selectByUserIdAndOrderNo(userId,orderNo);

if(order == null){

return ServerResponse.createByErrorMessage("用户没有该订单");

}

if(order.getStatus() >= Const.OrderStatusEnum.PAID.getCode()){

return ServerResponse.createBySuccess();

}

return ServerResponse.createByError();

}

}

我们会发现,上面的大多数是直接从支付宝Demo中的Main类中复制过来的,我们只是更改了对应的参数。上面第四行代码我们用到了自己封装了一个根据订单号和用户Id来查询订单的方法。

2.4 *Mapper

Order selectByUserIdAndOrderNo(@Param("userId") Integer userId,@Param("orderNo") Long orderNo);

Order selectByOrderNo(Long orderNo);

2.5 *Mapper.xml

<select id="selectByUserIdAndOrderNo" parameterType="map" resultMap="BaseResultMap">

select

<include refid="Base_Column_List"/>

from mmall_order

where order_no = #{orderNo}

and user_id = #{userId}

</select>

<select id="selectByOrderNo" resultMap="BaseResultMap" parameterType="long" >

select

<include refid="Base_Column_List"/>

from mmall_order

where order_no=#{orderNo}

</select>

2.6 Const类

public enum OrderStatusEnum{

CANCELED(0,"已取消"),

NO_PAY(10,"未支付"),

PAID(20,"已付款"),

SHIPPED(40,"已发货"),

ORDER_SUCCESS(50,"订单完成"),

ORDER_CLOSE(60,"订单关闭");

OrderStatusEnum(int code,String value){

this.code = code;

this.value = value;

}

private String value;

private int code;

public String getValue() {

return value;

}

public int getCode() {

return code;

}

public static OrderStatusEnum codeOf(int code){

for(OrderStatusEnum orderStatusEnum : values()){

if(orderStatusEnum.getCode() == code){

return orderStatusEnum;

}

}

throw new RuntimeException("么有找到对应的枚举");

}

}

public interface AlipayCallback{

String TRADE_STATUS_WAIT_BUYER_PAY = "WAIT_BUYER_PAY";

String TRADE_STATUS_TRADE_SUCCESS = "TRADE_SUCCESS";

String RESPONSE_SUCCESS = "success";

String RESPONSE_FAILED = "failed";

}

public enum PayPlatformEnum{

ALIPAY(1,"支付宝");

PayPlatformEnum(int code,String value){

this.code = code;

this.value = value;

}

private String value;

private int code;

public String getValue() {

return value;

}

public int getCode() {

return code;

}

}

public enum PaymentTypeEnum{

ONLINE_PAY(1,"在线支付");

PaymentTypeEnum(int code,String value){

this.code = code;

this.value = value;

}

private String value;

private int code;

public String getValue() {

return value;

}

public int getCode() {

return code;

}

public static PaymentTypeEnum codeOf(int code){

for(PaymentTypeEnum paymentTypeEnum : values()){

if(paymentTypeEnum.getCode() == code){

return paymentTypeEnum;

}

}

throw new RuntimeException("么有找到对应的枚举");

}

}

3、支付接口测试(一)

打开地址,显示二维码。

4、支付接口测试(二)

给沙箱环境配置我们的回调地址。

打开沙箱环境:登录 - 支付宝

在图上所示配置我们的回调地址。

由于我们是在本地开发,所以需要将本地IP映射到公网,这个教程有讲怎么将本地IP映射到公网:https://blog.csdn.net/czjlghndcy/article/details/81130029

映射好公网IP之后,我们就将对应生成的共网IP以及定义的接口访问地址粘贴到沙箱环境中的回调地址中即可~

支付一个未支付的案例

对生成的二维码进行支付

查询订单状态

显示已支付,So,我们的回调接口以及订单状态查询接口测试成功啦~

相关知识

花好网帮助中心—支付方式
广州百合花鸿运酒店服务设施
广州南沙花园酒店服务设施
武汉五月花大酒店服务设施
花好网帮助中心—投诉处理
博客园美化 背景Sakura JS樱花特效
Hello Kitty 永生花束
web支付基础教程
kylinH5框架之项目组件理解
珠芽繁殖(关于珠芽繁殖介绍)

网址: AliPay https://m.huajiangbk.com/newsview849396.html

所属分类:花卉
上一篇: 微信小程序集成V3支付接口
下一篇: java如何第三方支付