最近本人刚做了手机APP支付宝支付功能,主要分为六步,在这里主要记录代码部分。

第一步:创建应用并获取APPID

要在您的应用中接入支付宝App支付能力,需要通过创建应用的方式接入蚂蚁相关接口并进行开发,基于对行业及业务场景痛点的理解,创造能够满足市场需要的解决方案,以应用的形式服务用户。

若还未成为开放平台的入驻服务商或者商户, 请完成入驻指引。入驻完成后,您需要去蚂蚁金服开放平台(open.alipay.com),在开发者中心中创建您的应用,会为您生成应用唯一标识(APPID),并且可以申请开通开放产品使用权限,通过APPID您的应用才能调用开放产品的接口能力。需要详细了解开放平台创建应用步骤请参考《开放平台应用创建指南》。

在创建应用后即生成应用的标识APPID,使用支付宝账号登录开放平台后,在“我的应用”中按下图方式查看APPID。

第二步:配置应用

应用创建完成后,需要给应用添加App支付功能,这样就可以在你的应用里使用App支付能力。此时该应用为开发中状态,只能在沙箱环境下进行调试。应用开发完成后,请开发者自行进行验收和安全性检查(安全性检查可参考《开放平台第三方应用安全开发指南》),验收检查完成后可申请上线。应用申请上线后,会同时申请此列表的功能,接口即生效,这个状态下的应用能够调用生产环境的接口。

开始添加

签约

在使用这些能力的时候,需要在开放平台里进行签约,这时候约定的合同就生效了。也可以代替商户签约。

开始签约

配置密钥

为了保证交易双方(商户和支付宝)的身份和数据安全,开发者在调用接口前,需要配置双方密钥,对交易数据进行双方校验。

1、了解下支付宝密钥处理体系:

2、密钥包含:

应用公钥:由商户自己生成的RSA公钥(与应用私钥必须匹配),商户需上传应用公钥到支付宝开放平台,以便支付宝使用该公钥验证该交易是否是商户发起的。
应用私钥:由商户自己生成的RSA私钥(与应用公钥必须匹配),商户开发者使用应用私钥对请求字符串进行加签。
支付宝公钥:支付宝的RSA公钥,商户使用该公钥验证该结果是否是支付宝返回的。

生成密钥后在开放平台开发者中心进行密钥配置,配置完成后可以获取支付宝公钥。具体方法流程请参见上传应用公钥并获取支付宝公钥。

3、配置生成的密钥等应用信息。配置的详细步骤请参考《配置应用环境》。

注:签名验签常见问题排查

支付宝开放平台SDK封装了签名和验签过程,只需配置账号及密钥参数,强烈建议使用。更多签名问题的自助排查流程,可以参考支付宝验签专区的未使用开放平台SDK的自助排查流程。关于同步通知和异步通知的验签规则,可参考验签教程。

更多关于签名教程和签名工具下载等问题,请参见签名专区。

第三步:集成和开发

接入移动支付需要集成两个SDK,客户端SDK需要集成在商户自己的APP中,用于唤起支付宝APP并发送交易数据,并在支付宝APP返回商户APP时获得支付结果。服务端SDK需要商户集成在自己的服务端系统中,用于协助解析并验证客户端同步返回的支付结果和异步通知。

服务端SDK可在蚂蚁金服开放平台下载

第四步:调用接口

为了避免在线上生产环境联调过程中遇到问题,建议在沙箱环境中联调通过后再在线上生产环境进行联调,具体操作步骤见沙箱联调指南。如果需要在线上调用接口,需要参考下面第六步:应用上线后再进行接口调用,不然会报出“无权限错误”。

系统交互流程:

如图,以Android平台为例:
图中虚线标识商户链路,实线标识支付宝链路。
第4步:调用支付接口:此消息就是本接口所描述的支付宝客户端SDK提供的支付对象PayTask,将商户签名后的订单信息传进payv2方法唤起支付宝收银台,交易数据格式具体参见请求参数说明。
第5步:支付请求:支付宝客户端SDK将会按照商户客户端提供的请求参数发送支付请求。
第8步:接口返回支付结果:商户客户端在第4步中调用的支付接口,会返回最终的支付结果(即同步通知),参见客户端同步返回。
第13步:用户在支付宝APP或H5收银台完成支付后,会根据商户在手机网站支付API中传入的前台回跳地址return_url自动跳转回商户页面,同时在URL请求中附带上支付结果参数。同时,支付宝还会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的形式将支付结果作为参数通知到商户系统,详情见支付结果异步通知。

除了正向支付流程外,支付宝也提供交易查询、关闭、退款、退款查询以及对账等配套API。

特别注意:

  • 构造交易数据并签名必须在商户服务端完成,商户的应用私钥绝对不能保存在商户APP客户端中,也不能从服务端下发。
  • 同步返回的数据,只是一个简单的结果通知,商户确定该笔交易付款是否成功需要依赖服务端收到支付宝异步通知的结果进行判断。
  • 商户系统接收到通知以后,必须通过验签(验证通知中的sign参数)来确保支付通知是由支付宝发送的。建议使用支付宝提供的SDK来完成,详细验签规则参考异步通知验签。

使用SDK快速接入

App支付API必须通过支付宝提供的移动端SDK来调用。

交易操作

以下大致记录针对alipay.trade.app.pay接口的相关代码:

1.APP客户端调用应用服务端,应用服务端通过alipay.trade.app.pay接口传入订单参数,将alipay.trade.app.pay接口返回的AlipayTradeAppPayResponse返回给APP客户端,由APP唤起支付宝客户端。

package com.lvqutour.service.aliService.impl;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.lvqutour.api.LvQuResult;
import com.lvqutour.mapper.AlipayFeedbackMapper;
import com.lvqutour.pojo.AlipayFeedback;
import com.lvqutour.result.AlipayResultInfo;
import com.lvqutour.service.aliService.IAliPayService;
import com.lvqutour.service.aliService.IAliResultComparisonService;
import com.lvqutour.utils.payLogUtil.MdcPut;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;/*** Created with IntelliJ IDEA.* Date: 2018/3/13 17:04* User: pc* Description:*/public class AliPayServiceImpl implements IAliPayService {static Logger logger = Logger.getLogger(AliPayImpl.class);@Autowiredprivate AlipayFeedbackMapper alipayFeedbackMapper;@AutowiredIAliResultComparisonService aliResultComparison;//正式环境//appidpublic static String APP_ID="2017112000054898";//pkcs8的私钥public static String APP_PRIVATE_KEY="WXMMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCGyZ8uny8HuYqyff5e4AgIVJZYaUndxDKWF18DnfcliR0xO941P2OXtNh/vSxrq8ifv4EdoTBI1QLOXA3LtfHgXIMUCWAYJn+bf1I5u/UKe3SMhYmEPX74qQNceqG3Wa5MB6/6XvzXK1fajCgAV6zhtCw13kqcJ9ayIWVcB4jnjBsGpyL6Fok3CJl2CwgWm5eT1NL/jShHHjnWmA5bjMOZbSr1wYMthxZUeL3A8QBd4KOoFq7Uge6qlrv1uagIA45l69TttSQYJUaYMfwLgyZnOr9KkImTVdSxnsmkAYoIEVEn3qj+vaEKVOB+9vGKG1yAP3zX7D5H4q2d/9WWti4dAgMBAAECggEAbyRh9fecuCnujDAISANDnFrjfhOTrSHS9KBg4IKpAHKHd8l9+TpDzRx6SRqcPkxwKgmnVd9MCUJcBf0yAwAMaozeKO9yJXfZUUczbhfmfrY97IFQW5K52CDFfMRCBQYWCutr2G/q3SIIV1Wqxl2FWLdQnTqnGwxepJOVGMW9xe8tPmQlOXWU8F9EpGSlixlhZPPhJTEw7Gj/jCohpyxnqe7K38PJGmpEwH33rKc76bnOVtYBxLUxs740bnytv/bNvGB81u8MsRX/qPb7T9KIn5zzdxjFjULW/crNqWi6zlAdmAjvafbu+TEaD8Q4JsQCrkFdArStTJn/zngb5M+JAQKBgQDvU7Wdw42QgiJcdQQ7iAAe+/adpPv+vbADut5i/qEL+FORBBmVIN1CqyzELn0zimRbW5F8LttuiC2WnIMk1VcdMRr/pdp1KesOW1Etg13tiiQfE6VAwg87CjEyohFxXzpRR4ayOd+TVm05/bnB15frQYQS/L2vi/MRUIOC9HGV5QKBgQCQLX+exHyzP+OGF3S7Rt8sWcQufTuFo9YSFLTKeI64ssSJKXxhkhX0DQfyjG6HlQpmKMzIta+kNW+Wc4vzu4oBA3stn5HALGexjcIz879jc11nib5kMGXFHq8jBSq0T4Ax5pqNlrc0KyGUsFD4Ka63ARdM4giLxaQikpLmEjOz2QKBgQC6vNY5AxyyZNfqzGNBEB0IEBGdb94wJlHwlx5un7+JV3nc7RYJBlueaXHEoYGPdaxYnFooS2dsF1V67yRk2RHf9TDbyM1sHgkKarYsjRP9BIyqsul+Xe0EZC9/EnYJwAQA545yAjYxAH65gQAv/8jKB5TGO+7Fyq0eFXSH+bOnAQKBgEae0qUM71vJjoOu15Gn7EbIDW0MEGysTH38wHVwSdA0WEorFO6h5Lju7RakLLuiiD5z+6LQQ6E2P1s9a67ODJHkh6BYSccMuRniKt7RpMxsxLKjaKugfSjpl7WaoUlCq7NFliyGR2R5P/CZ0H9Nw3OGSEhzauYzv+rjSqsA/Ww5AoGAYE91J5oxiTkFYE09fyAKWpq+hGH1a4i0+EwU71R71zWUFGX4kerVyQRStzIRlHWV1CSOZoT4Wt8PeWMRMLhsvRo9S9cVc0pUSPAwNMfcyWdBj2Ytl+jakH1HuRuBCGXnA+Lv+Kyvd6XL02EOE4XRpJmhJng+Rma43SvhyUCxCm8=";//支付宝公钥public static String ALIPAY_PUBLIC_KEY="WXMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkonhwBFgSsQu9omd4q0JE4JgVeJc321yo8it27L2ZdJ9qdRUqR9Me6pgc1lYPbUuRycmFSPY8mjSyNhavVxK5G7+9zIFfaIzC0bBSFVnrRL3JbI8gyLaRzh9cT8Hpp0bYUCbZzpdZ8tKP2eMc2HoynVR9lwX/hZrijYwlWGXbxYif1TMRIZEpPDTfw+4KbJ4I1rBx6qDf4jZLVnKuP11meAoR8VvrkF+Le717prWoleXp0yHUF2SoDzKh3OPEqZKKECe5Mr30BnFUCcLhSaxhbkMtAje9MPvsVSniAldGeZqwMzG3SvkauoB/AYWhrTN7NH1fapvN/f/lUPlgnuV7wIDAQAB";//签名方式public static String sign_type="RSA2";//编码格式public static String CHARSET="utf-8";//正式环境支付宝网关public static String url="https://openapi.alipay.com/gateway.do";//实例化客户端AlipayClient alipayClient = new DefaultAlipayClient(url, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY,sign_type);//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.payAlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();//调用支付宝客户端@Overridepublic LvQuResult alipay(String body, String subject, String totalAmount, int userId, int member_id, String outTradeNo) {//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();model.setBody(body);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给bodymodel.setSubject(subject);//商品的标题/交易标题/订单标题/订单关键字等model.setTotalAmount(totalAmount);//订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]model.setProductCode("QUICK_MSECURITY_PAY");//销售产品码,商家和支付宝签约的产品码model.setOutTradeNo(outTradeNo);//商户网站唯一订单号,请保证OutTradeNo值每次保证唯一model.setTimeoutExpress("30m");//该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。request.setBizModel(model);request.setNotifyUrl("http://www.lvqutour.com:8081/lvqutour/notify/aliPaynotify_url.jsp");//商户外网可以访问的异步地址AlipayTradeAppPayResponse response;try {response = alipayClient.sdkExecute(request);//这里和普通的接口调用不同,使用的是sdkExecutereturn LvQuResult.ok(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。} catch (AlipayApiException e) {e.printStackTrace();String massage = "alipay.trade.app.pay接口:订单签名错误";MdcPut.mdcPut(outTradeNo,new Date(),massage);logger.error("订单号:" + outTradeNo + massage);return LvQuResult.msg(false, "订单号:" + outTradeNo + massage);}}}

2.支付宝客户端支付后,支付宝服务端会发起异步通知到应用服务端(http://www.lvqutour.com:8081/lvqutour/notify/aliPaynotify_url.jsp),服务端进行解签校验,确认支付状态。应用服务端回调页代码如下:

<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<%@ page import="java.util.*"%>
<%@ page import="java.util.Map"%>
<%@ page import="com.alipay.api.*"%>
<%@ page import="com.alipay.api.internal.util.*"%>
<%@ page import="org.springframework.web.context.support.WebApplicationContextUtils" %>
<%@ page import="org.springframework.web.context.WebApplicationContext" %>
<%@ page import="com.alibaba.druid.support.json.JSONUtils" %>
<%@ page import="org.apache.commons.logging.Log" %>
<%@ page import="org.apache.commons.logging.LogFactory" %>
<%@ page import="com.lvqutour.utils.payLogUtil.MdcPut" %>
<%@ page import="com.lvqutour.pojo.*" %>
<%@ page import="com.lvqutour.mapper.*" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%
/* ** 功能:支付宝服务器异步通知页面* 日期:2017-03-30* 说明:* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。* 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。*************************页面功能说明************************** 创建该页面文件时,请留心该页面文件中无任何HTML代码及空格。* 该页面不能在本机电脑测试,请到服务器上做测试。请确保外部可以访问该页面。* 如果没有收到该页面返回的 success* 建议该页面只做支付成功的业务逻辑处理,退款的处理请以调用退款查询接口的结果为准。*/Log log= LogFactory.getLog("aliPaynotify_url.jsp");//正式环境支付宝公钥String ALIPAY_PUBLIC_KEY="WXMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkonhwBFgSsQu9omd4q0JE4JgVeJc321yo8it27L2ZdJ9qdRUqR9Me6pgc1lYPbUuRycmFSPY8mjSyNhavVxK5G7+9zIFfaIzC0bBSFVnrRL3JbI8gyLaRzh9cT8Hpp0bYUCbZzpdZ8tKP2eMc2HoynVR9lwX/hZrijYwlWGXbxYif1TMRIZEpPDTfw+4KbJ4I1rBx6qDf4jZLVnKuP11meAoR8VvrkF+Le717prWoleXp0yHUF2SoDzKh3OPEqZKKECe5Mr30BnFUCcLhSaxhbkMtAje9MPvsVSniAldGeZqwMzG3SvkauoB/AYWhrTN7NH1fapvN/f/lUPlgnuV7wIDAQAB";//编码格式String CHARSET="utf-8";WebApplicationContext context=WebApplicationContextUtils.getWebApplicationContext(this.getServletConfig().getServletContext());OrderMapper orderMapper = (OrderMapper)context.getBean("orderMapper");AlipayFeedbackMapper alipayFeedbackMapper = (AlipayFeedbackMapper)context.getBean("alipayFeedbackMapper");MemberMapper memberMapper = (MemberMapper)context.getBean("memberMapper");MemberTypeMapper memberTypeMapper = (MemberTypeMapper)context.getBean("memberTypeMapper");NotificationMapper notificationMapper = (NotificationMapper)context.getBean("notificationMapper");//解签结果boolean signVerified;//异步通知解签结果boolean result = true;//异步通知的验证结果boolean verificationResult = false;//异步通知存入数据库结果boolean insertResult = false;//用户int userId = 1;//会员类型(会员表)byte memberTypeId = 1;//该笔订单Order order = null;//商户订单号、商户金额、卖家支付宝用户号、商户本身appidString out_trade_no = request.getParameter("out_trade_no");String total_amount = request.getParameter("total_amount");String seller_id = request.getParameter("seller_id");String app_id = request.getParameter("app_id");//request转换为MapMap<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);}/*实际验证过程建议商户务必添加以下校验:1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)4、验证app_id是否为该商户本身。*/try {signVerified = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET,"RSA2");if(signVerified) {//解签成功AlipayFeedback alipayFeedback = new AlipayFeedback();OrderExample orderExample = new OrderExample();orderExample.createCriteria().andOrderNumEqualTo(out_trade_no);order = orderMapper.selectByExample(orderExample).get(0);if(order != null && order.getPrice() == Double.valueOf(total_amount).doubleValue() && seller_id.equals("2088821541811607") && app_id.equals("2017112000054898")){//将异步通知获得到的Map转换成String,并存入数据库String notification = JSONUtils.toJSONString(params);String id = params.get("out_trade_no");alipayFeedback.setOutTradeNo(id);alipayFeedback.setNotification(notification);if(alipayFeedbackMapper.insertSelective(alipayFeedback) != 1){insertResult = false;//记录日志---"支付宝服务端异步通知数据存储异常";MdcPut.mdcPut(out_trade_no,new Date(),"支付宝服务端异步通知数据存储异常");log.error("订单号:" + out_trade_no + "支付宝服务端异步通知数据存储异常");}else{insertResult = true;}verificationResult = true;//insertResult/verificationResult/result均为true,再为userId和memberTypeId赋值userId = order.getUserId();memberTypeId = order.getMemberId().byteValue();}else{verificationResult = false;//记录日志---"支付宝服务端异步通知数据与商户系统中数据不匹配,或商户系统数据查询出现异常");MdcPut.mdcPut(out_trade_no,new Date(),"支付宝服务端异步通知数据与商户系统中数据不匹配,或商户系统数据查询出现异常");log.error("订单号:" + out_trade_no + "支付宝服务端异步通知数据与商户系统中数据不匹配,或商户系统数据查询出现异常");}}else {//解签失败result = false;//记录日志---"解签失败";MdcPut.mdcPut(out_trade_no,new Date(),"解签失败");log.error("订单号:" + out_trade_no + "解签失败");}} catch (AlipayApiException e) {result = false;e.printStackTrace();}
//根据回调数据结果,插入购买的会员信息if(result && verificationResult & insertResult) {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");order.setPayType(1);order.setState((byte) 3);order.setUpdateTime(new Date());if (orderMapper.updateByPrimaryKeySelective(order) != 0){Member member = new Member();Date beginTime;Date overTime;//查询是否已经是会员MemberExample memberExample = new MemberExample();memberExample.createCriteria().andUserIdEqualTo(userId);List<Member> members = memberMapper.selectByExample(memberExample);if (members.size() != 0) {      //已经是会员member = members.get(0);member.setUpdateTime(new Date());beginTime = member.getOverTime();//使用Calendar类的add方法进行年度和月度的推进Calendar calendar = Calendar.getInstance();calendar.setTime(beginTime);if (memberTypeId == 2) {calendar.add(Calendar.YEAR, +1);//日期加1年overTime = calendar.getTime();member.setOverTime(overTime);} else if (memberTypeId == 1) {calendar.add(Calendar.MONTH, +1);//日期加1个月overTime = calendar.getTime();member.setOverTime(overTime);}if (memberMapper.updateByPrimaryKeySelective(member) != 0) {//记录日志---"会员购买成功");MdcPut.mdcPut(out_trade_no, new Date(), "会员购买成功");log.error("订单号:" + out_trade_no + "会员购买成功");MemberType memberType = memberTypeMapper.selectByPrimaryKey(order.getMemberId());Notification notification = new Notification();notification.setUserId(userId);notification.setNotification("尊敬的用户,你在"+order.getUpdateTime()+"购买的"+memberType.getName()+",购买成功!VIP有效日期截止至:"+simpleDateFormat.format(member.getOverTime()));notification.setCreateTime(order.getUpdateTime());notification.setIsRead(0);notificationMapper.insertSelective(notification);out.print("success");} else {//记录日志---"会员购买失败");MdcPut.mdcPut(out_trade_no, new Date(), "会员购买失败,原因:会员信息存入数据库失败!");log.error("订单号:" + out_trade_no + "会员购买失败,原因:会员信息存入数据库失败!");}} else {      //不是会员beginTime = new Date();//使用Calendar类的add方法进行年度和月度的推进Calendar calendar = Calendar.getInstance();calendar.setTime(beginTime);member.setUserId(userId);member.setMemberTypeId(memberTypeId);member.setBeginTime(beginTime);member.setCreateTime(new Date());if (memberTypeId == 2) {calendar.add(Calendar.YEAR, +1);//日期加1年overTime = calendar.getTime();member.setOverTime(overTime);} else if (memberTypeId == 1) {calendar.add(Calendar.MONTH, +1);//日期加1个月overTime = calendar.getTime();member.setOverTime(overTime);}if (memberMapper.insertSelective(member) != 0) {//记录日志---"会员购买成功";MdcPut.mdcPut(out_trade_no, new Date(), "会员购买成功");log.error("订单号:" + out_trade_no + "会员购买成功");MemberType memberType = memberTypeMapper.selectByPrimaryKey(order.getMemberId());Notification notification = new Notification();notification.setUserId(userId);notification.setNotification("尊敬的用户,你在"+order.getUpdateTime()+"购买的"+memberType.getName()+",购买成功!VIP有效日期截止至:"+simpleDateFormat.format(member.getOverTime()));notification.setCreateTime(order.getUpdateTime());notification.setIsRead(0);notificationMapper.insertSelective(notification);out.print("success");} else {//记录日志---"会员购买失败");MdcPut.mdcPut(out_trade_no, new Date(), "会员购买失败,原因:会员信息存入数据库失败!");log.error("订单号:" + out_trade_no + "会员购买失败,原因:会员信息存入数据库失败!");}}}else{//记录日志---"订单状态修改失败");MdcPut.mdcPut(out_trade_no, new Date(), "订单状态修改失败,数据库通讯异常");log.error("订单号:" + out_trade_no + "订单状态修改失败,数据库通讯异常");}}else{//记录日志---"会员信息存入数据库失败");MdcPut.mdcPut(out_trade_no,new Date(),"验证异常或数据库通讯失败");log.error("订单号:" + out_trade_no + "验证异常或数据库通讯失败");out.print("fail");}%>

3.支付宝支付完成后,APP客户端携带支付宝返回的数据,再次请求应用服务端,应用服务端将此数据与支付宝的异步通知数据进行对比,返回给APP客户端最终的支付状态:

//将异步通知从数据库取出与客户端返回的请求数据做比较@Overridepublic Boolean getClientFeedback(AlipayResultInfo alipayResultInfo) {String out_trade_no = alipayResultInfo.getAlipay_trade_app_pay_response().getOut_trade_no();Boolean result;//将异步通知从数据库取出AlipayFeedback alipayFeedback;alipayFeedback = alipayFeedbackMapper.selectByPrimaryKey(out_trade_no);if(alipayFeedback == null){MdcPut.mdcPut(out_trade_no, new Date(), "appFeedback的值为空");logger.error("从数据库取出的appFeedback的值为空");result = false;}else{result = aliResultComparison.comparison(alipayFeedback,alipayResultInfo);}return result;}
}

其中aliResultComparison.comparison(alipayFeedback,alipayResultInfo)方法代码如下:

//APP客户端返回信息与支付宝服务端返回信息对比@Overridepublic Boolean comparison(AlipayFeedback alipayFeedback, AlipayResultInfo alipayResultInfo) {Boolean result = false;String app_id = alipayResultInfo.getAlipay_trade_app_pay_response().getApp_id();String total_amount = alipayResultInfo.getAlipay_trade_app_pay_response().getTotal_amount();String seller_id = alipayResultInfo.getAlipay_trade_app_pay_response().getSeller_id();String trade_no = alipayResultInfo.getAlipay_trade_app_pay_response().getTrade_no();Map alipayFeedbackMap = JSON.parseObject(alipayFeedback.getNotification());if (alipayFeedbackMap.get("trade_no").equals(trade_no) && alipayFeedbackMap.get("total_amount").equals(total_amount) && alipayFeedbackMap.get("app_id").equals(app_id) && alipayFeedbackMap.get("seller_id").equals(seller_id)) {if (alipayFeedbackMap.get("trade_status").equals("TRADE_FINISHED")) {//判断该笔订单是否在商户网站中已经做过处理//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序//如果有做过处理,不执行商户的业务程序//注意://退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知result = false;} else if (alipayFeedbackMap.get("trade_status").equals("TRADE_SUCCESS")) {//判断该笔订单是否在商户网站中已经做过处理//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序//如果有做过处理,不执行商户的业务程序//注意://付款完成后,支付宝系统发送该交易状态通知/*int payResult = orderMapper.updateByPrimaryKeySelective(order);if(payResult == 1){result = true;//记录日志}else{result = false;//记录日志}*/result = true;}}return result;}

具体可参见蚂蚁金服开放平台文档中心快速接入

第五步:调试应用

支付能力直接涉及到交易与资金,为了方便开放者调试支付能力,我们已经准备好沙箱环境,包括沙箱环境账号和沙箱版支付宝钱包,这样就可以在沙箱环境调试了。具体操作步骤见沙箱联调指南。

第六步:上线应用

商户本身应用上线时候,也要把支付宝开放平台的应用上线。

手机APP使用支付宝支付(服务端)相关推荐

  1. 手机APP调用支付宝支付(java服务端)

    最近项目中涉及到调用支付宝支付接口,记录一下.拉进去配置一下直接可以用的 导包 <dependency><groupId>com.alipay.sdk</groupId& ...

  2. ThinkPHP5.0+APP+支付宝支付 服务端开发

    工作环境,支付宝账号是公司的,app应用和秘钥配置都是我自己申请的,这其中的流程暂且跳过. 一.准备工作 appid.应用私钥.应用公钥.支付宝公钥 二.配置文件 'alipay'=>['app ...

  3. uniapp/手机APP使用支付宝支付(服务端)

    博主介绍:✌全网粉丝4W+,全栈开发工程师,从事多年软件开发,在大厂呆过.持有软件中级.六级等证书.可提供微服务项目搭建与毕业项目实战.定制.远程,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经 ...

  4. 基于spring-boot+uni-app实现app支付功能(微信/支付宝)服务端

    基于spring-boot+uni-app实现app支付功能(微信/支付宝)服务端 支付宝支付 1 准备工作 申请支付能力 接口加签方式 2代码 依赖 支付宝支付配置类 支付宝控制层 异步通知 微信支 ...

  5. PHP 实现支付宝APP 支付 (服务端 + 客户端 + 异步)

    目录 一.使用实例 二.服务端 1.下载SDK 2.业务层 3.业务层返回实例 推荐使用联调工具: 4.回调层 三.客户端 总结 一.使用实例 官方信息: 二.服务端 1.下载SDK App 支付服务 ...

  6. java 支付宝服务端,支付宝app支付服务端的实现-Java版

    前言 最近在工作中需要使用支付宝app支付,在初次使用过程中也不可避免的出现了一些问题,那么本次随笔主要是概述支付宝app支付服务端的整个实现过程以及就服务端出现的一些问题做一些总结. 1.准备工作 ...

  7. APP接入支付宝支付完整流程及踩坑记录(含服务端)

    本篇主要讲解APP接入支付宝支付完整流程,包含服务端,内容稍长 要接入支付宝支付,需要将APP在支付宝平台创建应用,提交审核,并进行商户签约以获得支付能力 详细参阅官方文档https://docs.o ...

  8. 微信APP支付服务端和Android 端详解及其demo

    最近在开发APP微信支付和支付宝支付,Android 端和后端都是我自己开发的,发现两家公司的文档都不是很友好,特别是微信,接触过或者开发过的人都应该有所体会.因此我特意把开发的过程梳理了,做下记录, ...

  9. java app支付_Java 微信支付之APP支付服务端 (一)

    Java 微信支付之APP支付服务端 (一) 如图所示,这是服务端要集成的所有微信接口.至于在开放平台申请就不做赘述了.主要流程,1.下单,2.异步通知,3.查询. 一.微信统一下单请求交易 /** ...

最新文章

  1. 再见 Xshell!这个开源的终端工具更酷炫!
  2. python定义16进制数组_python 文件转成16进制数组的实例
  3. 音乐上传网站_国外最受欢迎的15个BT下载网站
  4. Android实现计时与倒计时(限时抢购)的几种方法
  5. 以太网的分层架构_【新能源汽车专题】智能车时代的核心,电子架构系统深度解读,国内8股进入全球产业链(名单)...
  6. mybatis基础学习4-插件生成器(根据数据库的表生成文件)
  7. 使用Vanilla.js构建单页应用程序(SPA)网站
  8. PDF转图片文字丢失问题解决
  9. Java实现日历小程序【代码】
  10. 二十四节气—处暑,暑气渐轻,热力不减。
  11. 为什么mysql填不了数据库_求助,为何我的数据不能写入数据库
  12. python透视表画图_Python Pivot table透视表使用方法解析
  13. 虚拟小镇意识保存~认识脑电波
  14. CASIA-FASD活体检测库,MSU-MFSD库和NUAA库
  15. 力扣---LeetCode20. 有效的括号(栈)
  16. 介质服务器作用,爱数之介质服务器及介质同步技术
  17. 在虚拟机Ubuntu下安装java环境
  18. C语言编译时产生的警告:initializing ‘char *‘ with an expression of type ‘const char *‘ discards qualifiers
  19. 红帆以拥有四位MCITP再获微软“数据平台金牌能力”
  20. epic启动器在哪个文件夹_启动时|原神启动器在哪个文件中 启动器文件位置一览_234游戏网...

热门文章

  1. 计算机教育学 教育心理,用心教育学考研 | 教育心理学记忆口诀汇总,背就对了!...
  2. android 正则 ip,判断URL和IP的正则表达式
  3. PHP调用外部程序的方法
  4. POWER BI 笔记
  5. C++编程功底和常用规则
  6. 美哈佛大学图书馆证实发现首本人皮书
  7. hdu5944Fxx and string
  8. 第三届第五空间网络安全大赛WP(部分)
  9. 资深程序媛手把手教你如何从零基础进行电影数据数据分析采集!
  10. cbtc第二阶段总结