我的视频课程(基础):《(NDK)FFmpeg打造Android万能音频播放器》
我的视频课程(进阶):《(NDK)FFmpeg打造Android视频播放器》
我的视频课程(编码直播推流):《Android视频编码和直播推流》
目录:
移动大脑-SpringMVc搭建RestFul后台服务(一)-环境搭建
移动大脑-SpringMVc搭建RestFul后台服务(二)-配置mysql数据库
移动大脑-SpringMVc搭建RestFul后台服务(三)-RestFul接口编写(模拟用户注册登录)
移动大脑-SpringMVc搭建RestFul后台服务(四)-添加Token拦截器
移动大脑-SpringMVc搭建RestFul后台服务(五)-支付宝支付
移动大脑-SpringMVc搭建RestFul后台服务(六)-微信支付(Android)
移动大脑-SpringMVc搭建RestFul后台服务(七)-增量更新
上一篇博客《移动大脑-SpringMVc搭建RestFul后台服务(四)-添加Token拦截器》中为服务器端程序加了Token验证来确保一定的安全性,这篇和下一篇将介绍接入支付宝支付和微信支付功能。
先来看看这篇文章所达到的效果如图:
支付宝支付逻辑主要是:
APP端发送支付请求---->服务端生成本地支付订单---->服务端调用支付宝接口在支付宝后台生成支付宝支付订单---->支付宝生成支付订单返回给服务端---->服务端把支付宝返回的支付订单信息返回给APP端---->APP获取服务端返回的支付宝支付订单信息调起本地支付宝支付(支付宝客户端/支付宝H5支付页面)---->APP端成功付款---->支付宝同步通知APP支付结果并异步调用服务器回调接口告诉服务器支付结果---->服务端验证支付宝回调结果签名以及商户信息是否合法---->服务端处理相应的结果返回给支付宝服务器。这样就完成了一次支付过程。
开始搬砖
一、添加订单表“t_order”
1.1订单实体类OrderBean.java
package com.ywl5320.appservice.bean;
/**
* Created by ywl5320 on 2017/10/19.
*/
public class OrderBean extends BaseBean{
private Integer id;
private Integer userId;
private String phone;
private String orderNo;//订单号
private String payMoney; //支付金额
private String payGoods; //支付的商品名称
private Integer payStatus;//支付状态 0:未支付 1:支付成功
private String payTime;//支付时间
private Integer payWay;//支付方式 1:支付宝 2:微信
private String subject;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public String getPayMoney() {
return payMoney;
}
public void setPayMoney(String payMoney) {
this.payMoney = payMoney;
}
public String getPayGoods() {
return payGoods;
}
public void setPayGoods(String payGoods) {
this.payGoods = payGoods;
}
public Integer getPayStatus() {
return payStatus;
}
public void setPayStatus(Integer payStatus) {
this.payStatus = payStatus;
}
public String getPayTime() {
return payTime;
}
public void setPayTime(String payTime) {
this.payTime = payTime;
}
public Integer getPayWay() {
return payWay;
}
public void setPayWay(Integer payWay) {
this.payWay = payWay;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}
1.2在entitis.hbm.xml中配置表结构
<class name="com.ywl5320.appservice.bean.OrderBean" table="t_order">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="userId" column="userId"></property>
<property name="phone" column="phone"></property>
<property name="orderNo" column="orderNo"></property>
<property name="payMoney" column="payMoney"></property>
<property name="payGoods" column="payGoods"></property>
<property name="payStatus" column="payStatus"></property>
<property name="payTime" column="payTime"></property>
<property name="payWay" column="payWay"></property>
</class>
二、编写Dao层支付代码
2.1 OrderDao.java,包含四个方法,可看注解
package com.ywl5320.appservice.dao;
import com.ywl5320.appservice.bean.OrderBean;
/**
* Created by ywl5320 on 2017/10/19.
*/
public interface OrderDao {
/**
* 生成订单
* @param orderBean
*/
void createOrder(OrderBean orderBean);
/**
* 根据订单ID获取订单
* @param orderNo
* @return
*/
OrderBean getOrderById(int userId, String orderNo);
/**
* 更新订单
* @param orderBean
*/
void updateOrder(OrderBean orderBean);
/**
* 获取订单信息
* @param orderNo
* @return
*/
OrderBean getOrderByOrNo(String orderNo);
}
2.2 OrderDaoImpl.java
package com.ywl5320.appservice.dao;
import com.ywl5320.appservice.bean.OrderBean;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import java.util.List;
/**
* Created by ywl5320 on 2017/10/19.
*/
public class OrderDaoImpl extends HibernateDaoSupport implements OrderDao{
public void createOrder(OrderBean orderBean) {
// TODO Auto-generated method stub
this.getHibernateTemplate().save(orderBean);
}
public OrderBean getOrderById(int userId, String orderNo) {
// TODO Auto-generated method stub
List<OrderBean> orders = (List<OrderBean>) this.getHibernateTemplate().find("from OrderBean where userId=? and orderNo=?", userId, orderNo);
if(orders != null && orders.size() > 0)
{
return orders.get(0);
}
return null;
}
public void updateOrder(OrderBean orderBean) {
// TODO Auto-generated method stub
this.getHibernateTemplate().update(orderBean);
}
public OrderBean getOrderByOrNo(String orderNo) {
// TODO Auto-generated method stub
List<OrderBean> orders = (List<OrderBean>) this.getHibernateTemplate().find("from OrderEntity where orderNo=?", orderNo);
if(orders != null && orders.size() > 0)
{
return orders.get(0);
}
return null;
}
}
2.3 在beans.xml中配置OrderDaoImpl
<bean id="orderDaoImpl" class="com.ywl5320.appservice.dao.OrderDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
三、编写支付Service层
3.1下载新版支付宝服务端APP支付SDK(https://docs.open.alipay.com/54/106370),然后添加到web/WEB-INF/lib中并添加到项目中。
3.2创建PayService.java
package com.ywl5320.appservice.service;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.ywl5320.appservice.bean.*;
import com.ywl5320.appservice.dao.OrderDao;
import com.ywl5320.appservice.dao.UserDao;
import com.ywl5320.appservice.util.CommonUtils;
import com.ywl5320.appservice.util.MD5;
import com.ywl5320.appservice.util.RestFulUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
* Created by ywl5320 on 2017/10/19.
*/
@Transactional
public class PayService {
public static final String ALI_APPID = "";
public static final String ALI_RSA2_PRIVATE_KEY = "";
public static final String ALI_PUBLIC_KEY = "";
String lockSuo = "createOrder";
@Autowired
private OrderDao orderDao;
public RestFulBean<BaseBean> createOrder(int userId, String payGoods, String payMoney, int payWay, String subject)
{
String payTime = String.valueOf(System.currentTimeMillis());
String orderNo = "";
OrderBean order = null;
AliPayBean aliPayBean = null;
WxPayBean wxPayBean = null;
synchronized (lockSuo) {
try {
orderNo = MD5.encryptMD5(userId + payTime + payMoney + subject + "md5_create_order");//生成订单ID
OrderBean orderBean = new OrderBean();
orderBean.setSubject(subject);
orderBean.setOrderNo(orderNo);
orderBean.setUserId(userId);
orderBean.setPayGoods(payGoods);
orderBean.setPayMoney(payMoney);
orderBean.setPayStatus(0);//0:未支付 1:已支付
orderBean.setPayTime(CommonUtils.getNowTime());
orderBean.setPayWay(payWay);//1:支付宝支付 2:微信支付
orderDao.createOrder(orderBean);
order = orderDao.getOrderById(userId, orderNo);
if(order != null)
{
if(payWay == 1)//支付宝
{
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", ALI_APPID, ALI_RSA2_PRIVATE_KEY, "json", "utf-8", ALI_PUBLIC_KEY, "RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("我是测试数据");
model.setSubject(orderBean.getSubject());
model.setOutTradeNo(orderBean.getOrderNo());
model.setTimeoutExpress("30m");
model.setTotalAmount(orderBean.getPayMoney());
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
request.setNotifyUrl("http://10.50.50.205:8080/pay/verifyalipayresult.do");//注意:实际情况填写自己的服务器接口地址,外网才能访问。
try {
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
aliPayBean = new AliPayBean();
aliPayBean.setOrderId(response.getOutTradeNo());
aliPayBean.setOrderInfo(response.getBody());
// System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
} catch (AlipayApiException e) {
e.printStackTrace();
}
}
else if(payWay == 2)//微信支付
{
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(payWay == 1)
{
if(aliPayBean != null)
{
return RestFulUtil.getInstance().getResuFulBean(aliPayBean, 0, "支付宝订单生成成功");
}
else
{
return RestFulUtil.getInstance().getResuFulBean(null, 1, "支付宝订单生成失败");
}
}
else if(payWay == 2)
{
return RestFulUtil.getInstance().getResuFulBean(null, 1, "微信支付研发中");
}
else
{
return RestFulUtil.getInstance().getResuFulBean(null, 1, "支付方式不对");
}
}
/**
* 支付宝验证,更新订单信息
* @param params
* @return
*/
public String verifyAliPay(Map<String, String> params)
{
OrderBean orderBean = orderDao.getOrderByOrNo(params.get("out_trade_no"));
if(orderBean != null)
{
orderBean.setPayStatus(1);//已经支付
orderDao.updateOrder(orderBean);
return "success";
}
return "fail";
}
}
这里需要填写自己申请的支付宝相关的APPID和key信息。生成支付订单参照支付宝文档:https://docs.open.alipay.com/54/106370
3.3在beans.xml中配置payService
<bean id="payService" class="com.ywl5320.appservice.service.PayService"/>
四、编写PayAction
package com.ywl5320.appservice.action;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.ywl5320.appservice.bean.BaseBean;
import com.ywl5320.appservice.bean.OrderBean;
import com.ywl5320.appservice.bean.RestFulBean;
import com.ywl5320.appservice.bean.UserBean;
import com.ywl5320.appservice.service.PayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Created by ywl5320 on 2017/10/19.
*/
@Controller
@RequestMapping("/pay")
public class PayAction {
@Autowired
private PayService payService;
String alilock = "alilock";
/**
* 生成订单
* @param userId
* @param payGoods
* @param payMoney
* @param payWay
* @param subject
* @return
*/
@ResponseBody
@RequestMapping(value="/createOrder.do", method= RequestMethod.PUT)
public RestFulBean<BaseBean> register(int userId, String payGoods, String payMoney, int payWay, String subject)
{
return payService.createOrder(userId, payGoods, payMoney, payWay, subject);
}
/**
* 支付宝回调接口
* @param request
* @param resp
* @return
*/
@ResponseBody
@RequestMapping(value="/verifyalipayresult.do", method=RequestMethod.POST)
public String verifyAliPayRight(HttpServletRequest request, HttpServletResponse resp)
{
synchronized (alilock) {
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] + ",";
}
params.put(name, valueStr);
}
try {
boolean flag = AlipaySignature.rsaCheckV1(params, PayService.ALI_PUBLIC_KEY, "utf-8", "RSA2");
if(flag)
{
if(params.get("trade_status").equals("TRADE_SUCCESS") && params.get("app_id").equals(PayService.ALI_APPID) && params.get("seller_id").equals("*****************"))
{
return payService.verifyAliPay(params);
}
}
} catch (AlipayApiException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "fail";
}
}
return "fail";
}
}
这里创建订单采用PUT方式,支付宝服务端异步回调参照支付宝文档:https://docs.open.alipay.com/54/106370
以上就完成了支付宝服务端的全部操作,注意:这里支付验证里面仅仅做了支付订单状态的更改,实际情况根据自身需求来处理,比如购买VIP服务,就需要给用户一个VIP状态和过期时间等信息。
最后给出一段客户端调用支付宝的代码,具体可见文末尾源码。
获取支付订单并调用支付宝支付:
btnAliPay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(MyApplication.getInstance().getUserBean() == null)
{
Toast.makeText(MainActivity.this, "请先登录", Toast.LENGTH_LONG).show();
return;
}
showLoadDialog("创建订单");
PayApi.getInstance().createOrder(MyApplication.getInstance().getUserBean().getId(), "支付宝支付测试", "0.01", 1, "新本版支付宝SDK支付", new HttpSubscriber<AliPayBean>(new SubscriberOnListener<AliPayBean>() {
@Override
public void onSucceed(final AliPayBean data) {
hideLoadDialog();
System.out.println("支付宝支付信息:" + data.getOrderInfo());
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(MainActivity.this);
Map<String, String> result = alipay.payV2(data.getOrderInfo(),true);
Message msg = new Message();
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
}
@Override
public void onError(int code, String msg) {
hideLoadDialog();
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}
}, MainActivity.this));
}
});
支付结果处理:
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
PayResult payResult = new PayResult((Map<String, String>) msg.obj);
String resultStatus = payResult.getResultStatus();
// 判断resultStatus 为9000则代表支付成功
if (TextUtils.equals(resultStatus, "9000")) {
// 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
} else {
// 该笔订单真实的支付结果,需要依赖服务端的异步通知。
Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
}
}
};
到这里,就完成了支付宝的支付了。附:支付宝的支付还可以全程在客户端下单支付,但是为了安全,不暴露支付宝信息,还是在服务端下单最为保险。
源码下载:GitHub AppServiceRestFul 下一篇文章将会添加微信支付