支付相關(一):APP支付寶支付(JAVA服務端開發)
阿新 • • 發佈:2019-01-10
開發環境:springboot
最近一年兩個專案開發,其中APP支付這塊用到了微信支付,支付寶支付,以及轉賬到微信零錢,轉賬到支付寶賬號等功能,下面會分成4個文章來介紹。
具體的開通微信和支付寶問題我不再敘述,直接上程式碼,程式碼會打包放在CSDN去下載,沒有分的可以找我。
簽約注意下支付寶和微信都要開通APP支付,支付寶開通單筆轉賬的支付寶賬號,微信開通轉賬到零錢等
先從支付寶開始:
首先在pom.xml檔案中新增支付寶SDK依賴
1支付寶引數配置類
/** * 支付寶配置 */ public class AliPayConfig { //appid public static String APP_ID_USER = ""; //應用私鑰 public static String PRIVATE_KEY = ""; //應用公鑰 public static String APP_PUBLIC_KEY = ""; //支付寶公鑰 public static String ALI_PUBLIC_KEY =""; //字符集 public static String CHARSET = "utf-8"; //URLs支付 public static String URL = "https://openapi.alipay.com/gateway.do"; //資料格式 public static String FORMAT = "json"; //加密方式 public static String SIGN_TYPE = "RSA2"; //接收支付寶回撥地址notify_url //測試時候可以對映到本地地址可測試,不一定非要部署到線上 public static String NOTIFY_URL="可訪問的線上地址; //以下為支付寶授權登入所用 //授權服務對應的名稱 public static String AUTH_API_NAME="com.alipay.account.auth"; //授權服務介面名稱方法 public static String AUTH_API_METHOD="alipay.open.auth.sdk.code.get"; //授權app_name呼叫來源方的標識 public static String AUTH_APP_NAME="mc"; //呼叫業務的型別,常量值為 public static String AUTH_BIZ_TYPE="openservice"; // pid簽約的支付寶賬號對應的支付寶唯一使用者號 public static String AUTH_PID=""; // 產品碼 public static String AUTH_PRODUCT_ID="APP_FAST_LOGIN"; //授權範圍 public static String AUTH_SCOPE="kuaijie"; // 標識授權型別, public static String AUTH_TYPE="AUTHACCOUNT"; // }
上面引數配置一定要區分好,尤其是應用公鑰和支付寶公鑰。
2支付寶工具類,DTO,等
import java.io.Serializable; /** * @Description: 訂單表用dto */ public class OrderDto implements Serializable { private static final long serialVersionUID = -27273789824211424L; private Integer userId; //使用者ID private String orderNo; // 商戶訂單號,適配每個渠道對此引數的要求,必須在商戶系統內唯一 private Float amount; // 訂單總金額(必須大於0),單位為對應幣種的最小貨幣單位,人民幣為分 private String subject; // 商品標題,該引數最長為 32 個 Unicode 字元 private String body; // 商品描述資訊,該引數最長為 128 個 Unicode 字元 private String description; // 訂單附加說明,最多 255 個 Unicode 字元 private String wxZfbNum;//微信或支付寶支付成功微信支付寶生成的訂單號 private String aliAuthCode;//支付寶auth_code public Float getAmount() { return amount; } public void setAmount(Float amount) { this.amount = amount; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } 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 getWxZfbNum() { return wxZfbNum; } public void setWxZfbNum(String wxZfbNum) { this.wxZfbNum = wxZfbNum; } public String getAliAuthCode() { return aliAuthCode; } public void setAliAuthCode(String aliAuthCode) { this.aliAuthCode = aliAuthCode; } }
import java.io.Serializable; import java.util.List; public class ResultModel implements Serializable { private static final long serialVersionUID = -2376100248939876442L; private Integer status;//狀態 private String message;//返回資訊,成功或者失敗資訊 private String pkColumn;//生成主鍵的名稱 private Integer pk;//插入操作時返回的主鍵 private Integer maxId;//最大查詢返回id private List<Object> resultList;//查詢操作時返回的結果列表 private Object resultObject; public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Integer getPk() { return pk; } public String getPkColumn() { return pkColumn; } public void setPkColumn(String pkColumn) { this.pkColumn = pkColumn; } public void setPk(Integer pk) { this.pk = pk; } public Integer getMaxId() { return maxId; } public void setMaxId(Integer maxId) { this.maxId = maxId; } public List<Object> getResultList() { return resultList; } public void setResultList(List<Object> resultList) { this.resultList = resultList; } public Object getResultObject() { return resultObject; } public void setResultObject(Object resultObject) { this.resultObject = resultObject; } }
import java.util.Date;
/**
* 生成訂單編號使用
*/
public class UUID {
private static Date date = new Date();
private static StringBuilder buf = new StringBuilder();
private static int seq = 0;
private static final int ROTATION = 99999;
public static synchronized long next() {
if (seq > ROTATION)
seq = 0;
buf.delete(0, buf.length());
date.setTime(System.currentTimeMillis());
String str = String.format("%1$tY%1$tm%1$td%1$tk%1$tM%1$tS%2$05d", date, seq++);
return Long.parseLong(str);
}
private UUID(){
}
}
3支付程式碼實現
app請求後臺 和 支付寶支付成功通知
import com.alibaba.fastjson.JSONObject;
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.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
/**
* 支付寶訂單支付
*/
@RestController
@RequestMapping("/pay/alipay")
public class AliPayController {
//@Autowired
// private IMicroAliPayService microAliPayService;
@PostMapping("aliPayOrder")
public ResultModel aliPayOrder(@RequestBody OrderDto dto, HttpServletRequest request,
HttpServletResponse response) {
ResultModel resultModel = new ResultModel();
//例項化客戶端
AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.URL, AliPayConfig.APP_ID_USER, AliPayConfig.PRIVATE_KEY, AliPayConfig.FORMAT,AliPayConfig.CHARSET ,AliPayConfig.ALI_PUBLIC_KEY, AliPayConfig.SIGN_TYPE);
//例項化具體API對應的request類,類名稱和介面名稱對應,當前呼叫介面名稱:alipay.trade.app.pay
AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
//SDK已經封裝掉了公共引數,這裡只需要傳入業務引數。以下方法為sdk的model入參方式(model和biz_content同時存在的情況下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
String out_trade_no = String.valueOf(UUID.next());
model.setBody(dto.getBody());
model.setSubject(dto.getSubject());
model.setOutTradeNo(out_trade_no);
model.setTimeoutExpress("30m");
model.setTotalAmount(dto.getAmount()+"");//訂單價格
model.setProductCode("QUICK_MSECURITY_PAY");
aliRequest.setBizModel(model);
aliRequest.setNotifyUrl(AliPayConfig.NOTIFY_URL);//3為充值訂單
String orderStr = "";
try {
//這裡和普通的介面呼叫不同,使用的是sdkExecute
AlipayTradeAppPayResponse aliResponse = alipayClient.sdkExecute(aliRequest);
orderStr = aliResponse.getBody();//
//我是在這把支付訂單資訊做的儲存,生成預支付訂單,把orderStr傳給APP進行處理並支付
resultModel.setStatus(1);
resultModel.setMessage("生成預支付訂單成功");
resultModel.setResultObject(orderStr);
} catch (AlipayApiException e) {
e.printStackTrace();
}
return resultModel;
}
}
/**
* 支付成功接收支付寶支付成功通知
*
* @param request
* @throws UnsupportedEncodingException,AlipayApiException
*/
@PostMapping("aliPayInquiryNotify")
public void aliPayNotify(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {
//獲取支付寶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] + ",";
}
if (name.equals("trade_status")) {
System.out.println("交易狀態為:" + valueStr);
}
//亂碼解決,這段程式碼在出現亂碼時使用。
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
//切記alipaypublickey是支付寶的公鑰,別錯放應用公鑰,如果再驗籤這出問題,先排查是否放錯公鑰,一般是這個問題造成
//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
boolean flag = AlipaySignature.rsaCheckV1(params, AliPayConfig.ALI_PUBLIC_KEY, AliPayConfig.CHARSET, AliPayConfig.SIGN_TYPE);
//獲取支付寶的通知返回引數
if (flag) {//驗證成功
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 auth_app_id = new String(request.getParameter("auth_app_id").getBytes("ISO-8859-1"), "UTF-8");
//買家登入支付寶id
String buyer_logon_id = new String(request.getParameter("buyer_logon_id").getBytes("ISO-8859-1"), "UTF-8");
//交易時間
String gmt_payment = new String(request.getParameter("gmt_payment").getBytes("ISO-8859-1"), "UTF-8");
//交易金額
String invoice_amount = new String(request.getParameter("invoice_amount").getBytes("ISO-8859-1"), "UTF-8");
//這裡進行你的訂單狀態的更改,以及你的業務處理。處理完畢打印出success後,支付寶只會下發一次,否則會下發多次,可以檢視文件理解下
System.out.println("success");
} else {//驗證失敗
//TODO service 生成訂單支付失敗歷史記錄
System.out.println("fail");
}
}
4以上三步就是支付寶支付JAVA服務端的開發