1.1.什么是沙箱支付
支付宝沙箱支付(
Alipay Sandbox Payment
)是支付宝提供的一个模拟支付环境,用于开发和测试支付宝支付功能的开发者工具。在真实的支付宝环境中进行支付开发和测试可能涉及真实资金和真实用户账户,而沙箱环境则提供了一个安全、隔离的环境,使开发者能够模拟支付过程,测试支付功能,而不会使用真实资金。使用支付宝沙箱支付环境,开发者可以模拟各种支付场景,包括交易创建、支付请求、支付回调等,以验证支付功能的正确性和稳定性。沙箱环境中的所有交易和数据都是虚拟的,不会产生真实的交易或资金流动。
支付宝沙箱支付提供了开发者工具和接口,使开发者能够在模拟环境下进行支付流程的调试和测试。开发者可以在沙箱环境中创建测试账户、配置模拟的交易金额和状态,使用沙箱环境中的接口进行支付操作,并模拟支付回调接口接收支付结果。
通过使用支付宝沙箱支付,开发者可以更安全、更有效地进行支付功能的开发和测试,避免了对真实环境的影响和风险。一旦支付功能在沙箱环境中验证通过,开发者可以将其部署到真实的支付宝生产环境中,与真实用户进行交互和支付。
步骤:
登陆支付宝:支付宝开放平台
登录成功之后,点击控制台跳转到控制台主页面,将浏览器进度条滚动到最下面,选择沙箱,最后点击沙箱选项即可,如下:
前端代码:
$(".pay").click(function () { //地址,手机号,收货人,支付方式,快递方式 let el = $(".addres").find(".on") let person = el.find(".tit .fl").text() let address = el.find(".addCon p:first-child").text() let telephone = el.find(".addCon p:last-child").text() let pay = $(".way .on").attr('value') let mail = $(".dis .on").text() let ids = $(this).attr('data-ids') let order={ person,telephone,address,pay,mail,ids } $.post('/order/add',order,resp=>{ if(resp.code===200){ // 进入支付 let f = confirm("是否去结算?") if (f){ console.log(resp.data) location.href="/order/pay?oid="+resp.data }else { location.href="/" } } },"json") })
后端代码:
package com.lya.lyaspshop.controller; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.github.yitter.idgen.YitIdHelper; import com.lya.lyaspshop.config.AlipayConfig; import com.lya.lyaspshop.pojo.Goods; import com.lya.lyaspshop.pojo.Order; import com.lya.lyaspshop.pojo.OrderItem; import com.lya.lyaspshop.pojo.User; import com.lya.lyaspshop.resp.JsonResponseBody; import com.lya.lyaspshop.service.IOrderItemService; import com.lya.lyaspshop.service.IOrderService; import com.lya.lyaspshop.service.impl.GoodsServiceImpl; import com.lya.lyaspshop.service.impl.RedisServiceImpl; import com.lya.lyaspshop.vo.CartItemVo; import com.lya.lyaspshop.vo.OrderVo; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; @RestController @RequestMapping("/order") public class OrderController { @Autowired private RedisServiceImpl redisService; @Autowired private GoodsServiceImpl goodsService; @Autowired private IOrderItemService iOrderItemService; @Autowired private IOrderService iOrderService; @RequestMapping("/add") public JsonResponseBody<?> toOrder(User user, OrderVo orderVo){ String ids = orderVo.getIds(); List<CartItemVo> cartItems = redisService.loadCart(user, ids); //所有的购物车中商品的id集合 List<Long> gds = cartItems.stream().map(CartItemVo::getGid).collect(Collectors.toList()); //根据集合查询所有对应的商品 List<Goods> goods = goodsService.listByIds(gds); //遍历集合 赋值给对应的对象 for (Goods g : goods) { //找到对应id相同的元素 CartItemVo vo = cartItems.stream() .filter(v -> Objects.equals(v.getGid(), g.getGid())) .findFirst() .get(); //将商品g的属性赋值给vo BeanUtils.copyProperties(g,vo); } long oid = YitIdHelper.nextId(); //增加订单项 BigDecimal total=new BigDecimal(0); List<OrderItem> orderItems=new ArrayList<>(); for (CartItemVo item : cartItems) { //生成订单项 OrderItem orderItem = new OrderItem(); //赋值属性 BeanUtils.copyProperties(item,orderItem); orderItem.setQuantity(item.getNum()); orderItem.setOoid(YitIdHelper.nextId()); orderItem.setOid(oid); //放到一个集合中 批量增加 只会有一次数据库新增 orderItems.add(orderItem); //计算总价 + 当前的小计 total = total.add(item.cartprice()); } iOrderItemService.saveBatch(orderItems,5); //增加订单 Order order = new Order(); BeanUtils.copyProperties(orderVo,order); order.setOid(oid); order.setTotal(total); order.setUserId(user.getId()); order.setStatus(0); order.setCreateDate(new Date()); //订单插入数据库 iOrderService.save(order); //删除缓存元素 // redisService.removeCart(user,orderVo.getIds()); return JsonResponseBody.success(oid); } @RequestMapping("/pay") public String pay(User user, String oid){ // 得到结算的订单 Order order = iOrderService.getById(oid); // 调用支付页面 // 传来的是表单 String body = new AlipayConfig().goAlipay(order); return body; } // 这里传递来的数据: @RequestMapping("/payDone") public String payDone(Map<String,String> stringMap){ // 更具成功支付了id来修改状态: String oid = stringMap.get("out_trade_no"); iOrderService.update(new UpdateWrapper<Order>() .eq("oid",oid) .set("status",1) .set("pay_date",new Date())); // html语句可以解析,json数据只能响应 return "<script>\n" + " alert(\"支付成功\")\n" + " location.href=\"/\"\n" + "< /script>"; } }
这里我们要添加一条代码:(异步通知验签)
// 安全验证: Boolean b = Factory.Payment.Common().verifyNotify(stringMap); if (!b){ throw new BusinessException(JsonResponseStatus.UN_KNOWN); }
支付宝接口:(根据自己数据的来)
package com.lya.lyaspshop.config; import com.alipay.easysdk.factory.Factory; import com.alipay.easysdk.kernel.Config; import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse; import com.lya.lyaspshop.pojo.Order; import org.springframework.stereotype.Component; @Component public class AlipayConfig { private Config aliconfig() { Config config = new Config(); //沙箱支付宝地址 config.gatewayHost = "openapi-sandbox.dl.alipaydev.com"; //协议https config.protocol = "https"; //应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 config.appId = "9021000132623583"; //支付宝公钥 config.alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmexyLYPEgC4GHxHtCYEhThPEIOjOoMpr8w+bmOtAPpmLg3wrYt4xMFbTP4Wg8wBSWiLHgXtBl32BekY5PD0pOPRZ5VW8rL84uDt+wnCdS9PjXscFmDdzGvp4c1o4vgjQovylrfEf1AlLINYUsXaTp1Nk5IZGRxERLOoTKVI/COY/qyIvhSueS+gIadpgSXNn1R0K73zorJaKVhJS4WKtHfr1246sslQRptinaFiU5PAvQXzt5iaBLdqc3C0UGz1jTHgemaJOIW/SlhsR3CkKif0MX25IoCrwgpzYbv0JDoGG74pzAIOf2LuNaZbQRwQldYokTLVXIlWis1H0UqiYzQIDAQAB"; //签名方式 config.signType = "RSA2"; //商户私钥(应用私钥),您的PKCS8格式RSA2私钥 config.merchantPrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+y08ssgZZsO0y1Xr4dTTD3/Vh9rfpCJ79B5YLJlWhWDZ/+yfGBdyoMtMnPjvuqZNvyloNrxJFAlOc17A6JLEypnJw7G1W7BYIRur0cQx7bVjqqN/lCO9V1dsyOOKhFd+10lbkIgr1DY0FwY4z9bZuniPCRERvKu6M/485Iq68C8vQnBzlXPYSP9STmzLoNtkSDhC/4t5EQus5FEcpNkmXuDM9fGw1J2d4e3SKMZIj4h2+1qByhktEsc5HhKF4RCZK+MR0fhBStF8rRVd2hvDhjcgg3TVoYjvn0fLN2wMX03/lLsIA7+G4ORVxO9RS5PmhCLQab5lqa9YPFpqyoCB7AgMBAAECggEAAUE3CRU2o3pdZPswbtfee/dKFtXXicnLueBF5VbgM0pwOVE+hrfdJqIG73giTsSAurh69SIUna2RPTPR7d/15l5f3ExBv9OXpYBJ5UelDF7AufJYXpo7cLYSVfc3zlVlfj2e4qsypT/skIAgXkkcZQfXNlzaklyW6wh3Oan3ujbau1IQVE/jQBvTdUbAWapFcGJ5RH07MvuBJhz4rG2eAMANxT6JIp8+3rU1Pi//enhb5qTWa5xg+HFtqeNs5T+E0JPzR8ezWYkbCDiXL5iYE1jvoTeyaBfz7iKxRuN1bpgClg/DNB5j3JXo3Ke4SRtLf80WnCQFwV5paeWXUbdsuQKBgQDs7DiGoa1YD3yhXdkXJQONDp2EZb2679d3rC5m5qJsAZi+W+qWe4V7vqqmfJrFjAUe+eNWSaoaUXO9Z5Ps3dcNpFXBnOW0ODpBGcYnT8bu5qqWjRbYFMOAAznh895v/2uNtljWvYTHUrnYEP2ZNkiEzCg9IYgH1L5GWJ8hoPC+jQKBgQDOKDkHfSwELOOIFidOAJqV3qpeo4AzPW5X3GsNKg1fcnN9nRTgUqZhW+woGetXTbbCxuM24uQpVZqpVhZA+TcCBc+kj7yDwkyjhFtO7UQQRSBiyQm0w6qZY+1aKIwf1Z578Nsbcf07FEJjpfxV8YAuF6Vq9PcS1lI4N1rVi5m9JwKBgE6zYUuHpVddPZ8014pSp01SD40NZusUBNUiAv/3mPibxytkyRZXzc1/VpybQ6ZfjsvtYlElgzXe3L2MDJ1gS7GiZ0I7ZippiyBY+XPRklmFkiEUmQQKUa7SY4XlRnyZshaO/g/HQLYditJ1QmiEma5TSwKTguZnCxW/Fo1LMu15AoGBALEc/WHhuB8eMZyI69unySdY1SXZchqTfGkfhRkaN8L4oSAaBAV0/FxIjOsm2Xl32rwcArj01PBuCyHQQ+4uLYQfWfUXR+4qz4zr+UYlsYQI33n/HcefEsIVh6UdkMUI0c/JbXR2yggnr6HMyK1NfcIbrpHlQx974cdKR0+PT9WhAoGBANC3h8Y4FBaKOLcxwHCVDSUrCszCyE+NGvDJI2I5Q7Pjxb5hfHkYR0/cVG5aUJPElWWizaf+7wNCL9XtVCfoUYWZ3DffNs526DL3btN9zby2Tcq7q3NhvRc3ZezSd/XZkGpr7LhWK0wppi5TuvNlhl1VyoGtbMiNUPOrSNWepror"; return config; } public String goAlipay(Order order) { try { // 1. 设置参数(全局只需设置一次) Factory.setOptions(aliconfig()); // 2. 发起API调用(subject商品标题、outTradeNo订单编号、totalAmount总金额、returnUrl异步通知地址) AlipayTradePagePayResponse response = Factory.Payment.Page() .pay("商城项目收款", order.getOid().toString(), order.getTotal().toString(), //支付成功之后的异步通知(跳出到自己系统的哪个位置) "http://localhost:8080/order/payDone"); // 支付宝支付页面 return response.body; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } }
注意:
这里的支付宝公钥,应用私钥要填好:失败了多生成几次:
接入成功: