支付--支付宝手机网站支付(WAP)
介绍:
这是放在微信供公众号内的一个项目,支付模块设计到微信公众号支付和支付宝手机网站支付,这次把支付宝手机网站支付整理下来。
文档:
支付宝手机网站支付的开发文档: https://docs.open.alipay.com/203
签约:
首先要到支付宝开发者后台去签约支付宝手机网站支付方式。签约的要求是必须有能访问的网页,网页上有标明价格、名称等详细信息的商品,而且整个下单流程要完善,网站的完成度要高,这才能通过审核。
参考:
因为之前对接过支付宝的app支付,所以对接wap支付就容易得多。后台拼接参数的思路、方式都和之前一样。直接复用之前的代码,只需稍微修改几个参数就可以。
参见上一篇支付宝APP支付:http://blog.csdn.net/tonyfreak/article/details/78104519
思路:
1、先到支付宝开放平台创建应用获取APPID
2、配置应用的相关参数,签约申请开通对应的支付类型
3、获得支付权限后就可以着手进行代码编写:
①、组装参数分为公共请求参数和业务请求参数两部分。详见:https://docs.open.alipay.com/203/107090/
②、先把业务请求参数转成json放入公共请求参数biz_content 中
③、将公共请求参数进行签名操作
④、将签名后获得的签名参数放入公共请求参数sign中
⑤、将此时的公共请求参数进行url编码
⑥、将json数据传给前端
微信公众平台无法使用支付宝收付款的解决方案
微信中无法打开支付宝收款是微信浏览器限制所致,可以参考下图方法引导用户转到系统浏览器,即可用支付宝收款。点此下载。
微信中调用支付宝支付效果展示
后台代码
组装参数
/**
* 封装好参数,前台通过form表单来调起支付宝
*/
@RequestMapping("/alipayPayChongRequest")
@ApiOperation(value="支付宝充值起调的接口",httpMethod="POST",response=JsonUtil.class,notes="支付宝充值起调的接口---/alipayPayChongRequest")
public void alipayPayChongRequest(
@ApiParam(required=true,name="orderNumber",value="订单编号")@RequestParam(value="orderNumber") String orderNumber,
@ApiParam(required=true,name="orderTitle",value="订单标题")@RequestParam(value="orderTitle") String orderTitle,
@ApiParam(required=true,name="description",value="订单描述")@RequestParam(value="description") String description){
try{
if(orderNumber !=null && !orderNumber.equals("")
&& orderTitle !=null && !orderTitle.equals("")
&& description !=null && !description.equals("")){
BusWalletChong chong = busWalletChongService.findBusWalletChongById(orderNumber);// 根据订单主键id查询,订单编号就是主键id
String saleMoney = chong.getPrice().toString();
// 公共请求参数
Map<String, String> param = new HashMap<>();
param.put("app_id", AlipayConfig.appId); // 应用appId
param.put("method", "alipay.trade.wap.pay"); // 接口名称
param.put("format", "json"); //数据类型
param.put("charset", AlipayConfig.input_charset);//编码格式
param.put("timestamp", DatetimeUtil.formatDateTime(new Date()));//发送请求时间
param.put("version", "1.0");//调用接口版本,固定为1.0
param.put("notify_url", AlipayConfig.notify_url_chong);// 支付宝服务器主动通知商户服务
param.put("sign_type", AlipayConfig.sign_type);//签名类型
// 支付业务请求参数
Map<String, Object> pcont = new HashMap<>();
pcont.put("out_trade_no", orderNumber);// 订单号(综合采购单编号)
pcont.put("total_amount", String.valueOf(saleMoney));// 交易金额
pcont.put("subject", orderTitle); // 订单标题
pcont.put("body", description); // 对交易或商品的描述
pcont.put("product_code", "QUICK_WAP_WAY"); // 销售产品码
param.put("biz_content", JSON.toJSONString(pcont)); // 业务请求参数 不需要对json字符串转义
Map<String, String> payMap = new HashMap<>();
try {
param.put("sign", PayUtil.getSign(param, AlipayConfig.private_key)); // 业务请求参数
String orderStr = PayUtil.getSignEncodeUrl(param, true);
System.out.println(orderStr);
payMap.put("orderStr", orderStr);
} catch (Exception e) {
e.printStackTrace();
}
map1.put("msg", "成功");
map2.put("result", payMap);
}else{
map1.put("msg", "参数不全");
}
} catch (BusinessException e) {
e.printStackTrace();
map1.put("msg", "发生后台异常");
}
map.put("data", map2);
map.put("result", map1);
JsonUtil.writeJson(response, JsonUtil.objectToJson(map));
}
支付回调
/**
* 支付宝充值成功的回调接口
*/
@RequestMapping("/alipayPayCallBackWallet")
@ApiOperation(value="支付宝充值成功的回调接口",httpMethod="POST",response=JsonUtil.class,notes="支付宝充值成功的回调接口---pay/alipayPayCallBackWallet")
public String alipayPayCallBackWallet(){
try {
// 获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<String, String>();
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] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
// 商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
// 支付宝交易号
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
// 充值金额
String price = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
boolean check = AlipayNotify.verify(params);
if (check) {// 验证成功
// ////////////////////////////////////////////////////////////////////////////////////////
// 请在这里加上商户的业务逻辑程序代码
String orderNo = out_trade_no;// 提交订单返回的订单编号
// 支付宝交易号
String alipayOrderNo = trade_no;
BusWalletChong chong = busWalletChongService.findBusWalletChongById(orderNo);
if(chong != null && !"".equals(chong)){
if("1".equals(chong.getStatus())){// 支付状态为:已支付
response.getWriter().write(setXML("SUCCESS", ""));
}else{
BusWalletChong newChong = new BusWalletChong();
newChong.setPrice(new BigDecimal(price));
newChong.setPayId(alipayOrderNo);
newChong.setPayType(BusWalletChong.ALIPAY_ZHIFU_TYPE);
newChong.setId(orderNo);
boolean flag = busWalletChongService.updateWallet(newChong);
if(flag){
response.getWriter().write(setXML("SUCCESS", ""));
}else{
response.getWriter().write(setXML("FAIL", ""));
}
}
}else{
response.getWriter().write(setXML("FAIL", ""));
}
response.getWriter().write("SUCCESS");
} else {// 验证失败
response.getWriter().write("FAIL");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String setXML(String return_code, String return_msg) {
return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg
+ "]]></return_msg></xml>";
}
签名工具类
/**
* 对支付参数信息进行签名
*
* @param map
* 待签名授权信息
*
* @return
*/
public static String getSign(Map<String, String> map, String rsaKey) {
List<String> keys = new ArrayList<String>(map.keySet());
// key排序
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
boolean first = true;
for (String key : keys) {
if (first) {
first = false;
} else {
authInfo.append("&");
}
authInfo.append(key).append("=").append(map.get(key));
}
return SignUtils.sign(authInfo.toString(), rsaKey);
}
签名编码工具类
/**
* 返回签名编码拼接url
*
* @param params
* @param isEncode
* @return
*/
public static String getSignEncodeUrl(Map<String, String> map, boolean isEncode) {
String sign = map.get("sign");
String encodedSign = "";
if (CollectionUtil.isNotEmpty(map)) {
map.remove("sign");
List<String> keys = new ArrayList<String>(map.keySet());
// key排序
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
boolean first = true;// 是否第一个
for (String key: keys) {
if (first) {
first = false;
} else {
authInfo.append("&");
}
authInfo.append(key).append("=");
if (isEncode) {
try {
authInfo.append(URLEncoder.encode(map.get(key), AlipayConstants.CHARSET_UTF8));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
authInfo.append(map.get(key));
}
}
try {
encodedSign = authInfo.toString() + "&sign=" + URLEncoder.encode(sign, AlipayConstants.CHARSET_UTF8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return encodedSign.replaceAll("\\+", "%20");
}
前端代码
//点击支付宝付款
function payByAli(orderId,description,title){
$.ajax({
data:{orderNumber:orderId,orderTitle:title,description:description},
dataType:"json",
type:"post",
async: false,
url:"${ctxPath}/payZhiFuBao/alipayPayRequest",
success:function(msg){
if(msg.result.msg == "成功"){
//获取拼接好的url
var url = msg.data.result.orderStr;
var urls = "https://mapi.alipay.com/gateway.do?"+url;
console.log(urls);
$(".ali").attr("href",urls);
}
},
error:function(msg){
}
});
}
推荐阅读
-
支付--支付宝手机网站支付(WAP)
-
支付宝APP支付服务端代码实现
-
解决SpringBoot集成支付宝支付中文订单描述验签错误问题
-
【支付宝对接 (一)】支付宝手机网页支付官方Demo配合沙箱测试
-
java支付宝支付开发(沙箱模拟)
-
【支付宝支付】支付宝手机网站支付流程
-
支付开发(七)----支付宝开发之手机网站支付(H5支付)
-
记阿里电话面试的一个遗留问题:淘宝订单如何保证与支付宝订单的同步“? 博客分类: 原创 阿里面试异步系统同步kafka
-
记阿里电话面试的一个遗留问题:淘宝订单如何保证与支付宝订单的同步“? 博客分类: 原创 阿里面试异步系统同步kafka
-
支付宝&&银联官网 博客分类: pay pay