蚂蚁沙箱环境 (Beta) 是协助开发者进行接口功能开发及主要功能联调的辅助环境,通过配置参数、搭建页面及下载沙箱版支付宝可以测试PC端扫码支付功能以及达到快速熟悉搭建流程的目的。
注意:
登录支付宝开放平台——到达沙箱环境页面(首次登录需要入驻为自研开发者)
沙箱与线上不同,请注意更改代码配置。
注意:
密钥和应用(APPID)一一对应,即开发者需要为名下的每个应用分别设置密钥,且不同应用的密钥不能混用(意思就是一个应用只能对应一个密钥)。
支付宝开放平台支持开发者使用 普通公钥、公钥证书 两种签名方式;以下步骤采用普通公钥方式说明,如需采用公钥证书签名方式,请查阅官方帮助手册。
支付宝为技术开发人员提供了一键生成密钥工具(Windows版下载—MacOS版下载),可根据该软件生成一对RSA密钥、公钥证书申请CSR文件(在线申请应用公钥证书需要)。
生成密钥后,点击页面上的RSA2密钥 — 设置 — 公钥 。
注意:
生成的私钥需妥善保管,避免遗失,不要泄露。应用私钥需填写到代码中供签名时使用。应用公钥需提供给支付宝账号管理者上传到支付宝开放平台。
沙箱环境提供了沙箱版支付宝与测试账户,其中包含商户号和买家号,但是该账户只能在支付宝提供的测试APK上才能使用。沙箱环境下方有提供二维码可以下载沙箱版支付宝(也可以点击此处下载)。
下载完成后,可根据左侧栏中沙箱账号获取相应的账号密码等信息进行登录,如下图所示。
可自行下载官方DEMO进行查阅:https://opendocs.alipay.com/open/54/cyz7do
<dependency>
<groupId>com.alipay.sdkgroupId>
<artifactId>alipay-sdk-javaartifactId>
<version>4.9.100.ALLversion>
dependency>
import java.io.FileWriter;
import java.io.IOException;
/**
* 支付配置
*
* @author zxchengb
* @date 2020-04-04
*/
public class AlipayConfig {
/**
* 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
*/
public static String APP_ID = "201610xxxxxx";
/**
* 商户私钥,您的PKCS8格式RSA2私钥
*/
public static String MERCHANT_PRIVATE_KEY = "官方密钥工具中生成的私钥";
/**
* 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
*/
public static String ALIPAY_PUBLIC_KEY = "沙箱环境中的支付宝公钥";
/**
* 异步通知
*/
public static String notify_url = "异步通知回调地址";
/**
* 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
*/
public static String return_url = "支付完成后返回地址";
/**
* 签名方式
*/
public static String SIGN_TYPE = "RSA2";
/**
* 字符编码格式
*/
public static String CHARSET = "utf-8";
/**
* 请求参数格式
*/
public static String FORMAT = "json";
/**
* 支付宝网关(此处为沙箱环境网关)
*/
public static String GATEWAY_URL = "https://openapi.alipaydev.com/gateway.do";
/**
* 支付宝网关
*/
public static String LOG_PATH = "C:\\";
//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
*
* @param sWord 要写入日志里的文本内容
*/
public static void logResult(String sWord) {
FileWriter writer = null;
try {
writer = new FileWriter(LOG_PATH + "alipay_log_" + System.currentTimeMillis() + ".txt");
writer.write(sWord);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
RSA_PRIVATE_KEY:私钥,这个参数就是通过 支付宝开放平台开放助手 生成的应用公钥、应用私钥 中的应用私钥。
notify_url:异步通知,当你支付成功时,支付宝回调你本地启动项目的接口,必须是外网可以访问的,否则支付宝请求不到,但是又得是你本地的方法「不讨论线上测试」,所以这就需要用到内网映射(内网穿透),推荐使用免费版的 natapp(自行百度)。
ALIPAY_PUBLIC_KEY:支付宝公钥,注意这个参数不是你上边生成的应用公钥,而是的支付宝公钥。
/**
* 阿里支付视图类
*
* @author zxchengb
* @date 2020-04-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class AlipayVO {
/**
* 订单号
*/
private String outTradeNo;
/**
* 总金额
*/
private String totalAmount;
/**
* 商品名称
*/
private String subject;
}
/**
* 支付接口
*
* @author zxchengb
* @date 2020-04-04
*/
public interface AlipayService {
/**
* 支付宝支付调用接口
*
* @param response 响应体
* @param request 请求体
* @param alipayVO 参数视图类
* @throws IOException IO异常
* @throws AlipayApiException API异常
*/
void pay(HttpServletResponse response, HttpServletRequest request, AlipayVO alipayVO) throws IOException, AlipayApiException;
}
/**
* 支付接口实现类
*
* @author zxchengb
* @date 2020-04-04
*/
@Service
public class AlipayServiceImpl implements AlipayService {
/**
* 调取支付宝接口 web端支付
*/
DefaultAlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, AlipayConfig.APP_ID, AlipayConfig.MERCHANT_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGN_TYPE);
@Override
public void pay(HttpServletResponse response, HttpServletRequest request, AlipayVO alipayVO) throws IOException, AlipayApiException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
/* 同步通知,支付完成后,支付成功页面*/
alipayRequest.setReturnUrl(AlipayConfig.return_url);
/* 异步通知,支付完成后,需要进行的异步处理*/
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
alipayRequest.setBizContent("{\"out_trade_no\":\"" + alipayVO.getOutTradeNo() + "\","
+ "\"total_amount\":\"" + alipayVO.getTotalAmount() + "\","
+ "\"subject\":\"" + alipayVO.getSubject() + "\","
+ "\"body\":\"商品名称\","
+ "\"timeout_express\":\"90m\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
String body = alipayClient.pageExecute(alipayRequest).getBody();
response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
response.getWriter().write(body);
response.getWriter().flush();
response.getWriter().close();
}
}
/**
* 支付宝支付控制器
*
* @author zxchengb
* @date 2020-04-04
*/
@RestController
@Slf4j
public class AlipayController {
/**
* 支付服务类
*/
private AlipayService alipayService;
public AlipayController(AlipayService alipayService) {
this.alipayService = alipayService;
}
/**
* web 订单支付
*/
@GetMapping("payment/{TotalAmount}")
private void alipayPay(HttpServletResponse response, HttpServletRequest request, @PathVariable("TotalAmount") String totalAmount) {
AlipayVO vo = new AlipayVO()
.setOutTradeNo(UUID.randomUUID().toString().replace("-", ""))
.setTotalAmount(totalAmount)
.setSubject("捐赠计划");
log.info("发起支付传参:" + vo.toString());
try {
alipayService.pay(response, request, vo);
} catch (IOException | AlipayApiException e) {
log.error(e.getMessage());
}
}
}
function donate(amount){
window.location.href = "/payment/" + amount
}
上述项目后端采用SpringBoot框架,可根据自身项目需求进行扩展业务。
当提交支付请求后跳转至此页面(此时用沙箱支付宝扫码支付即可):
沙箱支付宝扫描结果:
PC端支付成功后结果:
若出现支付环境异常,请检查是否在一个浏览器中登录了多个支付宝账号,或者是否将应用公钥配置给多个应用。
至此,即已完成支付宝沙箱环境快速搭建,实现过程并不复杂,线上搭建流程大致也是如此,写下此文以便后续回顾。