注冊中的同步和異步
會(huì)員注冊流程.png
登陸
移動(dòng)端登錄接口.png
聯(lián)合第三方登陸
第三方聯(lián)合登錄流程.png
混合開發(fā)技術(shù)
混合開發(fā)技術(shù).png
加密
安全加密.png
支付架構(gòu)流程
支付架構(gòu)流程.png
同步回調(diào)
@Slf4j
@RestController
public class PayCallBackServiceImpl extends BaseApiService implements PayCallBackService {
@Autowired
private PaymentInfoDao paymentInfoDao;
// 同步回調(diào)
public ResponseBase synCallBack(@RequestParam Map<String, String> params) {
// 獲取支付寶GET過來反饋信息
try {
log.info("####同步回調(diào)開始####params:",params);
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key,
AlipayConfig.charset, AlipayConfig.sign_type); // 調(diào)用SDK驗(yàn)證簽名
// ——請?jiān)谶@里編寫您的程序(以下代碼僅作參考)——
if (!signVerified) {
return setResultError("驗(yàn)簽失敗!");
}
// 商戶訂單號
String out_trade_no = params.get("out_trade_no");
// 支付寶交易號
String trade_no = params.get("trade_no");
// 付款金額
String total_amount = params.get("total_amount");
JSONObject data = new JSONObject();
data.put("out_trade_no", out_trade_no);
data.put("trade_no", trade_no);
data.put("total_amount", total_amount);
return setResultSuccess(data);
} catch (Exception e) {
log.info("######PayCallBackServiceImpl##ERROR:#####", e);
return setResultError("系統(tǒng)錯(cuò)誤!");
}finally{
log.info("####同步回調(diào)結(jié)束####params:",params);
}
}
PayController同步回調(diào)隱藏get參數(shù)浴栽,get傳表單缘厢,表單里有post
// 同步回調(diào)
@RequestMapping("/callBack/synCallBack")
public void synCallBack(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
Map<String, String[]> requestParams = request.getParameterMap();
Map<String, String> params = new HashMap<String, String>();
for (Iterator<String> 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] + ",";
}
// 亂碼解決贴硫,這段代碼在出現(xiàn)亂碼時(shí)使用
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
PrintWriter writer = response.getWriter();
ResponseBase synCallBack = payCallBackFegin.synCallBack(params);
if (!synCallBack.getRtnCode().equals(Constants.HTTP_RES_CODE_200)) {
return;
}
LinkedHashMap data = (LinkedHashMap) synCallBack.getData();
String htmlFrom = "<form name='punchout_form'"
+ " method='post' action='http://127.0.0.1/callBack/synSuccessPage' >"
+ "<input type='hidden' name='outTradeNo' value='" + data.get("out_trade_no") + "'>"
+ "<input type='hidden' name='tradeNo' value='" + data.get("trade_no") + "'>"
+ "<input type='hidden' name='totalAmount' value='" + data.get("total_amount") + "'>"
+ "<input type='submit' value='立即支付' style='display:none'>"
+ "</form><script>document.forms[0].submit();" + "</script>";
writer.println(htmlFrom);
writer.close();
}
// 同步回調(diào),解決隱藏參數(shù)
@RequestMapping(value = "/callBack/synSuccessPage", method = RequestMethod.POST)
public String synSuccessPage(HttpServletRequest request, String outTradeNo, String tradeNo, String totalAmount) {
request.setAttribute("outTradeNo", outTradeNo);
request.setAttribute("tradeNo", tradeNo);
request.setAttribute("totalAmount", totalAmount);
return PAY_SUCCESS;
}
支付異步通知(其實(shí)和同步很像间护,多了冪等性判斷,和修改訂單)
@Override
public String asynCallBack(@RequestParam Map<String, String> params) {
// 1.日志記錄
log.info("#####支付寶異步通知synCallBack#####開始,params:{}", params);
// 2.驗(yàn)簽操作
try {
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key,
AlipayConfig.charset, AlipayConfig.sign_type); // 調(diào)用SDK驗(yàn)證簽名
log.info("#####支付寶異步通知signVerified:{}######", signVerified);
// ——請?jiān)谶@里編寫您的程序(以下代碼僅作參考)——
if (!signVerified) {
return Constants.PAY_FAIL;
}
// 商戶訂單號
String outTradeNo = params.get("out_trade_no");
// 調(diào)用訂單數(shù)據(jù)庫修改訂單表數(shù)據(jù)庫
// 3 處理冪等
PaymentInfo orderIdPayInfo = paymentInfoDao.getByOrderIdPayInfo(outTradeNo);
if (orderIdPayInfo == null) {
return Constants.PAY_FAIL;
}
// 判斷是否已經(jīng)支付過汁尺,如果已經(jīng)支付過,返回success,防止重試產(chǎn)生重復(fù)
Integer state = orderIdPayInfo.getState();
if (state == 1) {
return Constants.PAY_SUCCESS;
}
// 支付寶交易號
String tradeNo = params.get("trade_no");
orderIdPayInfo.setState(1);
orderIdPayInfo.setPlatformorderId(tradeNo);
orderIdPayInfo.setPayMessage(params.toString());
Integer updatePayInfo = paymentInfoDao.updatePayInfo(orderIdPayInfo);
if (updatePayInfo <= 0) {
return Constants.PAY_FAIL;
}
// 調(diào)用訂單接口通知修改訂單狀態(tài)
ResponseBase ordeResponseBase = orderFegin.updateOrderId(1l, tradeNo, outTradeNo);
if (!ordeResponseBase.getRtnCode().equals(Constants.HTTP_RES_CODE_200)) {
return Constants.PAY_FAIL;
}
return Constants.PAY_SUCCESS;
} catch (Exception e) {
log.error("####支付寶異步通知出現(xiàn)異常,ERROR:", e);
return Constants.PAY_FAIL;
} finally {
log.info("#####支付寶異步通知synCallBack#####結(jié)束,params:{}", params);
}
分布式事務(wù)
分布式產(chǎn)生原因
分布式事物產(chǎn)生原因.png
2PC
兩段提交協(xié)議.png
圖片1.png
消息中間解決
消息中間解決分布式事物.png
CAP
- 數(shù)據(jù)一致性(consistency):如果系統(tǒng)對一個(gè)寫操作返回成功狼荞,那么之后的讀請求都必須讀到這個(gè)新數(shù)據(jù);如果返回失敗拾积,那么所有讀操作都不能讀到這個(gè)數(shù)據(jù)拓巧,對調(diào)用者而言數(shù)據(jù)具有強(qiáng)一致性(strong consistency) (又叫原子性 atomic一死、線性一致性 linearizable consistency)[5]
- 服務(wù)可用性(availability):所有讀寫請求在一定時(shí)間內(nèi)得到響應(yīng),可終止承耿、不會(huì)一直等待
- 分區(qū)容錯(cuò)性(partition-tolerance):在網(wǎng)絡(luò)分區(qū)的情況下,被分隔的節(jié)點(diǎn)仍能正常對外服務(wù)
TCC
TCC(Try-Confirm-Cancel)瘩绒,則是將業(yè)務(wù)邏輯分成try锁荔、confirm/cancel兩個(gè)階段執(zhí)行其事務(wù)處理方式為:
1阳堕、 在全局事務(wù)決定提交時(shí)择克,調(diào)用與try業(yè)務(wù)邏輯相對應(yīng)的confirm業(yè)務(wù)邏輯;
2壹堰、 在全局事務(wù)決定回滾時(shí)骡湖,調(diào)用與try業(yè)務(wù)邏輯相對應(yīng)的cancel業(yè)務(wù)邏輯。 可見谆焊,TCC在事務(wù)處理方式上浦夷,是很簡單的:要么調(diào)用confirm業(yè)務(wù)邏輯,要么調(diào)用cancel邏輯