最近公司有一个需求是接入第三方支付(微信&支付宝),我接到了支付宝支付,所以本博客主要就简述我如何面像文档编程的经过,和中间遇到的小坑小洼,只要一步一步来操作,轻松接入alipay
微信支付的话,等有时间了,我向部门伙伴请教,看看套路是否差不多,到时候再写一篇关于接入微信支付的.
其实个人觉得,了解了一篇的话也一通百通了,毕竟还能差多少呢?

接入明确几点

  • 是否满足申请条件(非常最要,貌似个人的话搞不了的,不过可以玩一下沙箱测试)
  • 业务场景(非常重要)
  • 接入流程(最重要)
  • 文档开发(重要)

业务场景

首先蚂蚁金服开放平台先去看看你需要开发的场景是哪一类,然后确认无误之后,进行申请等.

接入流程

很爽的就是,我接手的时候是公司申请好了企业号,然后我根据具体业务需求

  1. 创建应用 : (我的业务是:手机网站支付),然后创建应用之后需要审核一个工作日,其实大概5-6小时的话就审核下来了,注意的是
  2. 添加功能 : 创建了应用还不具备开发的条件你还需要添加应用的功能,这一步必须要注意呀,我一开始以为可以了,结果测试的时候会报一个错(错误代码 insufficient-isv-permissions 错误原因: ISV权限不足),就是没有添加应用的功能的错误。需要审核2 - 3小时(审核速度还是比较快的~~~)
  3. 这个时候就可以看一下官方的DEMO or 相关文档了

文档开发

个人的建议,你这个时候可以先看一下相关的官方文档,以下推荐几个网址可以详细阅读

  • 手机网站支付文档
  • 手机网站支付请求参数说明
  • 网站调用支付宝进行支付
  • 如何生成RSA,RSA2密钥

好了,如果你开发中遇到问题,可以优先查这几个文档先,你会有意想不到的收获.

步骤01:下载官方的DEMO

https://docs.open.alipay.com/203/105910/
这里有JAVA PHP.NET等

如何查看?这是一个eclpise的工程,自行想办法[奸笑]
先查看 WebContent > index.html
然后根据button的点击事件查看对应的模块,如:支付、订单查询、订单退款、订单退款查询、账单下载

步骤02:生成RSA2密钥

https://openclub.alipay.com/read.php?tid=1833&fid=46
查看这篇文章,了解一下什么是密钥什么是公钥等,然后按照步骤生成应用的RSA2密钥,私钥将放入代码中,公钥传入应用中

注: 这里有一个坑,密钥长度2048指的是RSA2,我当初不知道,然后找资料,就在这里了解到

步骤03:编写代码
  • 添加依赖

<!--导入阿里支付相关依赖-->
<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>3.7.4.ALL</version>
</dependency><!--alibaba fastjson-->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.54</version>
</dependency>
  • AlipayConfig

/*** @author houyu* @createTime 2019/3/19 23:39*/
public class AlipayConfig {// 商户appidpublic static String APPID = "20190319635xxxxx";// 私钥 pkcs8格式的public static String RSA_PRIVATE_KEY = "MIIEvgIBADANBxxxxx ....  xxxxxxxxx+I";// 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问public static String notify_url = "http://your hostname/alipay/notify";// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址public static String return_url = "http://your hostname/alipay/return";// 请求网关地址,沙箱是:https://openapi.alipaydev.com/gateway.dopublic static String URL = "https://openapi.alipay.com/gateway.do";// 编码public static String CHARSET = "UTF-8";// 返回格式public static String FORMAT = "json";// 支付宝公钥(在应用中可以获取)public static String ALIPAY_PUBLIC_KEY = "MIIBIxxxxxxxx ....  xxxxxxxxx";// RSA2public static String SIGNTYPE = "RSA2";}
  • AlipayVo

import java.io.Serializable;/*** @author houyu* @createTime 2019/3/19 23:31*/
public class AlipayVo implements Serializable {/*** 订单名称*/private String subject;/*** 商户网站唯一订单号*/private String out_trade_no;/*** 该笔订单允许的最晚付款时间*/private String timeout_express;/*** 付款金额*/private String total_amount;/*** 销售产品码,与支付宝签约的产品码名称*/private String product_code;// getter and setter ....
}
  • AlipayUtil

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.juiniot.alipaydemo.config.AlipayConfig;import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.HashMap;
import java.util.Map;/*** @author houyu* @createTime 2019/3/20 8:38*/
public class AlipayUtil {/*** 处理请求参数* @param requestParams* @return*/public static Map<String, String> handleParams(Map<String, String[]> requestParams){Map<String, String> handleMap = new HashMap<>(requestParams.size());for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {String key = entry.getKey();String[] value = entry.getValue();handleMap.put(key, join(value, ","));}return handleMap;}/*** 数组转字符串  ["1", "2"]  ==> "1,2"* @param os* @param splitString* @return*/public static String join(Object[] os, String splitString){String s = "";if (os != null) {StringBuilder sBuffer = new StringBuilder();for (int i = 0; i < os.length; i++) {sBuffer.append(os[i]).append(splitString);}s = sBuffer.deleteCharAt(sBuffer.length() - 1).toString();}return s;}/*** 校验是否支付成功* @param handleParams* @return*/public static boolean rsaCheck(Map<String, String> handleParams) {boolean checkV1 = false;try {checkV1 = AlipaySignature.rsaCheckV1(handleParams, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);} catch (AlipayApiException e) {e.printStackTrace();}return checkV1;}/** ---------------------------------------单例模式---------------------------------------*/private static class SingletonHolder {private static final AlipayUtil INSTANCE = new AlipayUtil();}public static AlipayUtil get() {return SingletonHolder.INSTANCE;}/** ---------------------------------------单例模式---------------------------------------*//**  雪花算法生成ID,自带时间排序,一秒可以生成25万个ID左右 */// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)private final static long twepoch = 1288834974657L;// 机器标识位数private final static long workerIdBits = 5L;// 数据中心标识位数private final static long datacenterIdBits = 5L;// 机器ID最大值private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);// 数据中心ID最大值private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);// 毫秒内自增位private final static long sequenceBits = 12L;// 机器ID偏左移12位private final static long workerIdShift = sequenceBits;// 数据中心ID左移17位private final static long datacenterIdShift = sequenceBits + workerIdBits;// 时间毫秒左移22位private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private final static long sequenceMask = -1L ^ (-1L << sequenceBits);/* 上次生产id时间戳 */private static long lastTimestamp = -1L;// 0,并发控制private long sequence = 0L;private final long workerId;// 数据标识id部分private final long datacenterId;public AlipayUtil() {this.datacenterId = getDatacenterId(maxDatacenterId);this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);}/*** @param workerId     工作机器ID* @param datacenterId 序列号*/public AlipayUtil(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}/*** 获取下一个ID** @return*/public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {// 当前毫秒内,则+1sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {// 当前毫秒内计数满了,则等待下一秒timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;// ID偏移组合生成最终的ID,并返回IDlong nextId = ((timestamp - twepoch) << timestampLeftShift)| (datacenterId << datacenterIdShift)| (workerId << workerIdShift) | sequence;return nextId;}private long tilNextMillis(final long lastTimestamp) {long timestamp = this.timeGen();while (timestamp <= lastTimestamp) {timestamp = this.timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}/*** <p>* 获取 maxWorkerId* </p>*/protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {StringBuffer mpid = new StringBuffer();mpid.append(datacenterId);String name = ManagementFactory.getRuntimeMXBean().getName();if (!name.isEmpty()) {/** GET jvmPid*/mpid.append(name.split("@")[0]);}/** MAC + PID 的 hashcode 获取16个低位*/return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);}/*** <p>* 数据标识id部分* </p>*/protected static long getDatacenterId(long maxDatacenterId) {long id = 0L;try {InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);if (network == null) {id = 1L;} else {byte[] mac = network.getHardwareAddress();id = ((0x000000FF & (long) mac[mac.length - 1])| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;id = id % (maxDatacenterId + 1);}} catch (Exception e) {System.out.println(" getDatacenterId: " + e.getMessage());}return id;}/**  雪花算法生成ID,自带时间排序,一秒可以生成25万个ID左右 */}
  • AlipayController


import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.juiniot.alipaydemo.config.AlipayConfig;
import com.juiniot.alipaydemo.util.AlipayUtil;
import com.juiniot.alipaydemo.vo.AlipayVo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import java.util.Map;/*** @author houyu* @createTime 2019/3/19 23:29*/
@SuppressWarnings("Duplicates")
@Controller
@RequestMapping("/alipay")
public class AlipayController {/*** 测试代码是否跑通* @return*/@RequestMapping("/hello")@ResponseBodypublic String hello() {return "hello";}/*** 支付宝完成回调页面(不可信回调)*/@GetMapping("/return")@ResponseBodyprivate String alipayReturn(HttpServletRequest request) {Map<String, String[]> parameterMap = request.getParameterMap();Map<String, String> handleParams = AlipayUtil.handleParams(parameterMap);// 这里的校验没有多大的意思,不可信,直接获取out_trade_no跳转到对应的payed controller也可boolean rsaCheck = AlipayUtil.rsaCheck(handleParams);if (rsaCheck){System.out.println("验证通过");}else {System.out.println("验证失败");}// 获取订单号String out_trade_no = handleParams.get("out_trade_no");System.out.println("out_trade_no:" + out_trade_no);// 这里一般都是 重定向 payed的controller, 然后携带对应的信息如:return "redirect:/alipay/success?out_trade_no=" + out_trade_no;// payed的controller根据out_trade_no获取支付结果,并且给出页面提示return "支付完成";}/*** 支付宝完成结果异步的回调(可信回调)* @param request*/@PostMapping("/notify")@ResponseBodyprivate String alipayNotify(HttpServletRequest request) {Map<String, String[]> parameterMap = request.getParameterMap();Map<String, String> handleParams = AlipayUtil.handleParams(parameterMap);boolean rsaCheck = AlipayUtil.rsaCheck(handleParams);if (rsaCheck){System.out.println("验证通过");// 处理业务逻辑,更改支付状态等骚操作// ...}else {System.out.println("验证失败");}return rsaCheck ? "success" : "failure";}@RequestMapping("/pay")@ResponseBodypublic String pay() {AlipayVo alipayVo = new AlipayVo();// String out_trade_no = UUID.randomUUID().toString().replace("-", "");String out_trade_no = AlipayUtil.get().nextId() + "";System.out.println("out_trade_no:" + out_trade_no);// 设置订单单号,需要保证唯一性alipayVo.setOut_trade_no(out_trade_no);// 设置支付金额alipayVo.setTotal_amount("0.01");// 设置支付标题alipayVo.setSubject("houyu-test-title");// 设置订单有效时长(30分钟)alipayVo.setTimeout_express("30m");// 商品码(必须是QUICK_WAP_WAY),可以看文档 see: https://docs.open.alipay.com/203/107090/alipayVo.setProduct_code("QUICK_WAP_WAY");// 对象转为json字符串String json = JSONObject.toJSONString(alipayVo);// 建立连接AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);// 创建请求AlipayTradeWapPayRequest alipayTradeWapPayRequest = new AlipayTradeWapPayRequest();// 设置异步通知地址alipayTradeWapPayRequest.setNotifyUrl(AlipayConfig.notify_url);// 设置对调地址,就是说支付成功之后回调你的页面,你可以继续进行你的业务操作,但是这个是不可信任的,需要根据notify_url这边的回调确定支付是否成功alipayTradeWapPayRequest.setReturnUrl(AlipayConfig.return_url);// 封装请求支付信息alipayTradeWapPayRequest.setBizContent(json);String pageString;try {pageString = client.pageExecute(alipayTradeWapPayRequest).getBody();} catch (AlipayApiException e) {pageString = "request aliapy has error";e.printStackTrace();}return pageString;}}

以上代码应该算是清晰明了的了,希望对你有帮助…

建议:

对于这种开发形文档,随时可能更新,如果接入失败了,优先查看官网的文档解决,有可能接口更新了

交流:

如果接入过程有问题,可以一起交流!!!
for.houyu@qq.com
272694308@qq.com

Java接入支付宝支付(alipay)相关推荐

  1. Java接入支付宝支付测试买iPhone13 pro max

    Java接入支付宝支付 一.介绍 二.沙箱 三.支付流程 四.准备支付宝 五.代码 1.前端代码 2.后端代码 六.测试 一.介绍 支付宝官方网站 支付宝(中国)网络技术有限公司是国内的第三方支付平台 ...

  2. Java接入支付宝支付超级详细教程——从入门到精通

    ​ Java接入支付宝支付教程 源码下载 源码获取:点击获取源码 本文介绍了"二维码付款"的代码.其他支付方式的代码都在源码中. 一.创建应用 1.登录支付宝开放平台 支付宝开放平 ...

  3. Java接入支付宝支付教程

    Java接入支付宝支付教程 一.创建应用 1.登录支付宝开放平台 支付宝开放平台网址:https://open.alipay.com/platform/developerIndex.htm 2.创建一 ...

  4. java接入支付宝支付api

    https://b.alipay.com/登录支付宝商家服务开通支付,进入开放平台,查看开放平台密钥的APPID(应用ID),应用公钥,支付宝公钥,授权回调地址. 初次支付可能还没有设置应用密钥,可以 ...

  5. Java接入支付宝支付(沙箱)

    支付宝支付(沙箱) 支付宝支付 支付宝官方网站:https://www.alipay.com/ 支付宝(中国)网络技术有限公司是国内的第三方支付平台,致力于提供"简单.安全.快速" ...

  6. Java 接入支付宝支付 - 沙箱环境

    Table of Contents 一.沙箱环境 二.下载 Java 版 dome 三.生成RSA2密钥 四.代码如下 4.1 AlipayConfig 4.2 AlipayVo 4.3 Alipay ...

  7. 【超详细,全流程】java对接支付宝支付

    支付流程 一.对接前的准备 1.1创建应用,获取参数:APPID(使用沙箱环境可跳过) 1.1.1添加产品 1.1.2配置密钥,获取第二个参数:商户的私钥 1.1.3支付宝网关 1.1.4生成参数密钥 ...

  8. Android 接入支付宝支付实现

    接上篇android接入微信支付文章,这篇我们带你来接入支付宝支付服务 简介 首先要说明的是个人感觉接入支付宝比微信简单多了,很轻松的,所以同学们不要紧张~ 当然还是老规矩啦,上来肯定的贴上官网地址, ...

  9. Android接入支付宝支付实现

    接上篇android接入微信支付文章,这篇我们带你来接入支付宝支付服务 简介 首先要说明的是个人感觉接入支付宝比微信简单多了,很轻松的,所以同学们不要紧张~ 当然还是老规矩啦,上来肯定的贴上官网地址, ...

最新文章

  1. HDU - 5875 2016 ACM/ICPC 大连网络赛 H题 暴力
  2. [leetcode] Binary Tree Preorder Traversal
  3. python安装教程3.8.5-Python 3.8.5下载
  4. spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件)
  5. python学习笔记之迭代器
  6. mysql集群初始化配置_集群Cluster MySQL的安装配置和使用
  7. uva 11054——Wine trading in Gergovia
  8. MEncoder 使用实例
  9. [转] Android系统如何实现UI的自适应
  10. jsjavaScriptDate的时间格式转换,直接粘贴就可以使用
  11. windows优化大师8周年纪念版_P5SPS4体验版上线|青之驱魔师10周年纪念新卷发售【搞趣日报】...
  12. VMware Fusion Player 个人免费版
  13. 计算机网络中属于资源子网的是,属于计算机网络的资源子网
  14. EPLAN新建项目图纸
  15. Linux 网络包接收过程的监控与调优
  16. 今晚直播,你该了解的MySQL 8.0 SQL优化新特性
  17. 圆里面画一个最大的正方形_在圆里画一个最大的正方形发现了什么
  18. 基于matlab的单周期控制三相高功率因数并网逆变器的建模与仿真,基于Matlab的单周期控制三相高功率因数并网逆变器的建模与仿真...
  19. Mac_ThinkPHP报错:SQLSTATE[HY000] [1049] Unknown database 'XXX'
  20. 本科生搞AI在线崩溃:3个月才跑通GitHub模型,机器学习科研入门太难了吧

热门文章

  1. kafka适配Java jdk版本
  2. 优秀网页翻译:Adafruit - 只读树莓派 - 关机时避免 SD 卡损坏
  3. Excel数据筛选出来后修改再粘贴进去的方法
  4. springboot+mysql危险品监管系统-计算机毕业设计源码95185
  5. 复工后从简历被拒,到斩获蚂蚁offer,聊聊功不可没的公众号
  6. 华为云-容器化网站部署搭建调整版(亲测可用)
  7. Azure云服务基础知识
  8. iOS Pod 导入第三方库,如:Alamofire、HandyJSON
  9. SwitchHosts高效切换host -- 让开发,测试,线上环境切换更容易
  10. 5款前端切图工具大比拼:谁是最强切图神器