移動大腦-SpringMVc搭建RestFul後臺服務(五)-支付寶支付

 

我的視頻課程(基礎):《(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 下一篇文章將會添加微信支付

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章