对接【支付宝】支付接口

场景

最近在做支付宝的接口对接,之前做过一个版本,但是由于申请了新的账号以前旧的的接口对接就不能使用了

所以就开始对接新的版本接口对接,在这里也记录一下让那些还没有对接的兄弟少走点弯路。

准备

先申请一个企业账户

https://memberprod.alipay.com/account/reg/enterpriseIndex.htm

创建应用

去支付宝的开放平台

https://open.alipay.com/platform/home.htm

添加应用:

https://docs.open.alipay.com/200/105310

按照这个链接的文档一步一步操作;

账号准备好之后,就可以了解相关的接口了,以(即时到账)支付接口为例。

阅读接口文档

https://docs.open.alipay.com/270/alipay.trade.page.pay/

下载SDK

https://docs.open.alipay.com/54/103419

选择java版本

将sdk集成进入项目中

sdk中有一个jar包

将这个jar包上传到私服上去。

参考这个:

http://blog.csdn.net/huchunlinnk/article/details/17789175

项目引入sdk中的关键jar包

这里的gav的写法取决于你上传私服的时候的填写


com.alipay

alipay-api

1.0.0

处理AlipayConfig对象

取消AlipayConfig配置文件中的部分常量

打开下载sdk应该可以找到

将这个类中的前几个静态常量变成非静态的,以便可以支持多个配置对象。

/* *

*类名:AlipayConfig

*功能:基础配置类

*详细:设置帐户有关信息及返回路径

*修改日期:2017-04-05

*说明:

*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。

*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。

*/

@Data

publicclassAlipayConfig{

//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号

publicString app_id ="";

// 商户私钥,您的PKCS8格式RSA2私钥

publicString merchant_private_key ="";

// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。

publicString alipay_public_key ="";

// 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问

publicString notify_url ="";

// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问

publicString return_url ="";

// 签名方式

publicstaticString sign_type ="RSA2";

// 字符编码格式

publicstaticString charset ="utf-8";

// 支付宝网关

publicstaticString gatewayUrl ="https://openapi.alipay.com/gateway.do";

//日志路径

publicstaticString log_path ="C:\\";

}

公众号注:文中代码看不全可左右滑动

编写请求支付的接口

后端向支付宝发起支付的请求,在这个同时需要传递必要参数,下面我们就来编写如何向支付宝发起支付。

编写conroller层

/**

* 阿里支付控制器

*

*@authorWangSen(wangsenhehe@126.com)

*@Date2017年8月16日

*/

@Controller

@RequestMapping("/alipay")

publicclassAliPayController{

@Autowired

privateAlipayViewService alipayViewService;

/**

* 跳转到去支付的jsp页面

*

*@paramorderId 订单号

*

*@parampayAccountType 支付账号类型

*

*@parammodel 模型

*

*@throwsException

*/

@RequestMapping

publicvoidgotopay(longorderId, Model model)throwsException{

alipayViewService.setGoToPayInfo(orderId, model);

}

}

编写viewService层

/**

* 阿里支付页面服务类

*

*@authorWangSen(wangsenhehe@126.com)

*@Date2017年8月16日

*/

@Service

publicclassAlipayViewService{

@Autowired

privateNewAlipayBusinessService newAlipayBusinessService;

/**

* 设置去支付信息

*

*@paramorderId 订单id

*@parammodel 模型

*@parampayAccountType 支付账号类型

*

*@return构建的字符串

*/

publicvoidsetGoToPayInfo(longorderId, Model model)throwsException{

model.addAttribute("htmlStr", newAlipayBusinessService.buildPayRequest(orderId, payPrice,"报名费","略"));

}

}

编写service层

/**

* 新的阿里支付页面服务类

* 阿里升级接口之后使用这个服务类

*

*@authorWangSen(wangsenhehe@126.com)

*@Date2017年8月16日

*/

@Data

publicclassNewAlipayBusinessService{

/**

* 阿里的配置文件对象

*/

privateAlipayConfig alipayConfig;

/**

* 构建支付请求

*

*@paramorderId 订单号

*@parampayPrice 付款金额

*@paramorderName 订单名称

*@parambody 商品描述

*

*@returnhtml字符串

*/

publicStringbuildPayRequest(longorderId,longpayPrice, String orderName, String body)throwsException{

//获得初始化的AlipayClient

AlipayClient alipayClient = getAlipayClient();

//设置请求参数

String bizContent = getBizContent(ConvertUtil.obj2str(orderId), AmountUtils.changeF2Y(payPrice), orderName,

body);

returnalipayClient.pageExecute(setAlipayRequestParameters(bizContent)).getBody();

}

/**

* 设置阿里支付请求参数

*

*@parambizContent 包含关键参数的json字符串

*

*@returnAlipayTradePagePayRequest对象

*/

privateAlipayTradePagePayRequestsetAlipayRequestParameters(String bizContent){

AlipayTradePagePayRequest alipayRequest =newAlipayTradePagePayRequest();

alipayRequest.setReturnUrl(alipayConfig.getReturn_url());

alipayRequest.setNotifyUrl(alipayConfig.getNotify_url());

alipayRequest.setBizContent(bizContent);

returnalipayRequest;

}

privateAlipayClientgetAlipayClient(){

AlipayClient alipayClient =newDefaultAlipayClient(AlipayConfig.gatewayUrl, alipayConfig.getApp_id(),

alipayConfig.getMerchant_private_key(),"json", AlipayConfig.charset,

alipayConfig.getAlipay_public_key(), AlipayConfig.sign_type);

returnalipayClient;

}

/**

* 获取业务的关键内容

*

*@paramout_trade_no 订单号

*@paramtotal_amount 付款金额

*@paramsubject 订单名称

*@parambody 商品描述

*

*@return拼接之后的json字符串

*/

privateStringgetBizContent(String out_trade_no, String total_amount, String subject, String body){

ExceptionUtil.checkEmpty(out_trade_no,"订单号不能为空");

ExceptionUtil.checkEmpty(total_amount,"价格不能为空");

ExceptionUtil.checkEmpty(subject,"订单名称不能为空");

ExceptionUtil.checkEmpty(body,"商品描述不能为空");

StringBuffer sb =newStringBuffer();

sb.append("{");

sb.append("\"out_trade_no\":\"").append(out_trade_no).append("\",");

sb.append("\"total_amount\":\"").append(total_amount).append("\",");

sb.append("\"subject\":\"").append(subject).append("\",");

sb.append("\"body\":\"").append(body).append("\",");

sb.append("\"product_code\":\"FAST_INSTANT_TRADE_PAY\"");

sb.append("}");

returnsb.toString();

}

}

通过xml文件配置支付对象

<?xml version="1.0" encoding="UTF-8"?>

xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"

>

<!-- 数理化支付配置对象 -->

<!-- 阿里支付业务服务类 -->

编写jsp页面

<%@pageimport="com.we.core.common.util.DateTimeUtil"%>

<%@pagelanguage="java"contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

支付宝即时到账交易接口

${htmlStr }

测试

页面访问:

localhost:8091/alipay/gotopay.json?orderId=232323

就可以看到支付页面了;

编写支付的异步通知接口

用户支付完成之后支付宝会通过你配置的的notify_url的值进行回调,

我需要编写这个逻辑,以完成整个的支付流程。

编写controller层

/**

* 阿里支付控制器

*

*@authorWangSen(wangsenhehe@126.com)

*@Date2017年8月16日

*/

@Controller

@RequestMapping("/alipay")

publicclassAliPayController{

@Autowired

privateAlipayViewService alipayViewService;

/**

* 支付完成

*/

@Void

@NotSso

@ResponseBody

@RequestMapping

publicvoidpayFinish()throwsException{

alipayViewService.payFinish();

}

}

编写viewService层

/**

* 阿里支付页面服务类

*

*@authorWangSen(wangsenhehe@126.com)

*@Date2017年8月16日

*/

@Service

publicclassAlipayViewService{

@Autowired

privateNewAlipayBusinessService newAlipayBusinessService;

/**

* 支付完成

*

*@throwsIOException io异常

*/

publicvoidpayFinish()throwsException{

newAlipayBusinessService.payFinish();

}

}

编写处理支付完成的servie

/**

* 新的阿里支付页面服务类

* 阿里升级接口之后使用这个服务类

*

* @author   WangSen(wangsenhehe@126.com)

* @Date     2017年8月16日

*/

@Data

publicclassNewAlipayBusinessService{

/**

* 阿里的配置文件对象

*/

privateAlipayConfig alipayConfig;

/**

* 支付完成

*

* @throws Exception 异常对象

*/

publicvoidpayFinish() throws Exception{

HttpServletRequest request = MvcUtil.getRequest();

PrintWriterout= MvcUtil.getResponse().getWriter();

//获取支付宝POST过来反馈信息

Mapparams= getParames(request);

if(!isSuccess(params)) {

fail(out);

return;

}

longorderId = getOrderId(params);

longpayPrice = getTotalFee(params);

try{

//编辑你支付完成之后的逻辑

success(out);

}catch(Exception e) {

fail(out);

}

}

/**

* 获取订单id

*

* @param params 请求参数

* @return 订单id

*/

privatelonggetOrderId(Mapparams){

String order_no =params.get("out_trade_no");

returnConvertUtil.obj2long(order_no);

}

/**

* 获取总金额

*

* @param params 请求参数

* @return 总金额

*/

privatelonggetTotalFee(Mapparams){

String total_fee =params.get("total_amount");

returnConvertUtil.obj2long(AmountUtils.changeY2F(total_fee));

}

/**

* 校验支付宝支付是否成功

*

* @param params http请求

* @return 成功即为真

* @throws AlipayApiException

*/

privatebooleanisSuccess(final Mapparams) throws AlipayApiException{

boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipay_public_key(),

AlipayConfig.charset, AlipayConfig.sign_type);//调用SDK验证签名

if(!signVerified) {

returnfalse;

}

//交易状态

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

if(!trade_status.equals("TRADE_FINISHED") && !trade_status.equals("TRADE_SUCCESS")) {

returnfalse;

}

returntrue;

}

/**

* 成功

*

* TODO 重构方法名

* @param out 输出流

*/

privatevoidsuccess(PrintWriterout){

out.println("success");

}

/**

* 失败

*

* TODO 重构方法名

* @param out 输出流

*/

privatevoidfail(PrintWriterout){

out.println("fail");

}

/**

* 获取参数

*

* @param request HttpServletRequest对象

*

* @return 返回支付宝携带的参数

*/

privateMapgetParames(HttpServletRequest request){

Mapparams=newHashMap();

@SuppressWarnings("unchecked")

Map requestParams = request.getParameterMap();

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

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

@SuppressWarnings("cast")

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

String valueStr ="";

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

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

}

//乱码解决,这段代码在出现乱码时使用

//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");

params.put(name, valueStr);

}

returnparams;

}

}

做的过程可能用到的资源

支付接口以及异步通知接口的参数详解:

https://docs.open.alipay.com/270/105902/

生成公钥私钥的步骤:

https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1

服务端的sdk:

https://docs.open.alipay.com/203/105910

即时到账新老版本接口对比:

https://docs.open.alipay.com/270/106759

扩展阅读

互联网支付系统整体架构详解

微信支付之扫码支付

支付系统设计:支付系统的账户模型

最强解析:支付宝系统架构内部剖析

Spring MVC+Spring+Mybatis实现支付宝支付功能(图文详解)

来源:https://www.cnblogs.com/wangsen/p/7512391.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容