手机APP使用支付宝支付(服务端)

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

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

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

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

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

1.png


第二步:配置应用

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

开始添加

签约

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

开始签约

配置密钥

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

1、了解下支付宝密钥处理体系:
1.png
2、密钥包含:

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

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

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

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

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

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

第三步:集成和开发

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

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

第四步:调用接口

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

系统交互流程:
image

如图,以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;}

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

第五步:调试应用

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

第六步:上线应用

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



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/70659.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信中使用支付宝进行支付

微信中使用支付宝不能直接使用&#xff0c;由于微信内置浏览器的原因&#xff0c;在微信中使用支付宝时无法跳转出去&#xff0c;支付宝官网给出了实例文档 支付宝官网地址 下载后 将其例子融入到vue中使用 步骤&#xff1a; 第一步&#xff1a;将ap.js放在vue项目中 第二步&a…

php 使用 yansongda/pay 进行微信,支付宝支付

最近项目使用yansongda/pay 进行微信与支付宝开发&#xff0c;整理一下自己开发中遇到的问题 yansongda/pay composer 扩展地址 https://packagist.org/packages/yansongda/pay // 使用composer update 更新下载yansongda包扩展 复制 文档中 支付宝支付&#xff0c;微信支…

pc接入支付宝支付功能

1. 后端调用支付宝api 2.前端拿到后端返回的url 3.前端在页面使用iframe嵌入请求支付宝 代码例&#xff1a; // 后端返回的链接, 放入iframe的src中。这里使用官方提供的链接 const alipayUrl "https://openapi.alipay.com/gateway.do?timestamp2013-01-01 08:08:0…

Android接入支付宝实现支付功能

Android接入支付宝实现支付功能 我本来是想直接讲Android支付这一块的&#xff0c;包括支付宝&#xff0c;微信&#xff0c;其他第三方整合支付等&#xff0c;但是微信开放平台他对我的账号做了限制&#xff0c;所有我今天就先把重心放在支付宝的支付上&#xff0c;也算是写得…

如何使用支付宝支付接口

支付宝支付 入门 """ 1&#xff09;支付宝API&#xff1a;六大接口 https://docs.open.alipay.com/270/105900/2&#xff09;支付宝工作流程(见下图)&#xff1a; https://docs.open.alipay.com/270/105898/3&#xff09;支付宝8次异步通知机制(支付宝对我们服…

Android应用接入支付宝实现支付功能

记得很早以前公司项目中添加过移动支付这一块&#xff0c; 包括微信&#xff0c;支付宝&#xff0c;银联等第三方的整合。 但是后来懒于总结就没留下什么&#xff0c; 最近公司项目打算添加&#xff0c;所以打算简单总结一下&#xff0c;记上一笔以备将来使用。 毕竟第三方的支…

支付宝支付接口的调用(支付宝支付的实现)

首先&#xff0c;下面是调用支付宝接口的官网&#xff1a; 支付宝开放平台https://open.alipay.com/platform/home.htmhttps://open.alipay.com/platform/home.htm我们这里只演示沙箱环境下的&#xff0c;正式环境需要审核什么的&#xff0c;正式环境与此配置类似&#xff0c;…

支付宝和微信的支付功能如何进行测试?

要分析测试点之前&#xff0c;我们先来梳理一下测试思维。总结来说&#xff0c;任何事物的测试思路都可以总结如下&#xff1a; 第一步&#xff1a;梳理产品的核心业务流程&#xff1a;明白这是个什么项目&#xff0c;实现了什么业务&#xff0c;以及是怎么实现的&#xff1f;…

Android App接入支付功能——支付宝支付

接入前准备 接入APP支付能力前&#xff0c;开发者需要完成以下前置步骤。 本文档展示了如何从零开始&#xff0c;使用支付宝开放平台服务端 SDK 快速接入App支付产品&#xff0c;完成与支付宝对接的部分。 接入准备——支付宝开发能力 一.下载官方sdk&#xff0c;将sdk放入…

推荐一个优秀人工智能(AI)学习网站:Quester AI

网站链接如下&#xff1a; QuesterAI 简要介绍&#xff1a; Quester AI全方位地整合AI学习资源&#xff0c;对每一个从业者&#xff0c;学习者开放&#xff0c;并且是免费开放。同时&#xff0c;Quester AI努力为AI领域学习者和爱好者大量提供持续的AI开源资源&#xff0c;给…

人工智能的数学方法

要成为一名出色的 AI 软件工程师&#xff0c;需要了解多少数学知识&#xff1f;&#x1f914; 在之前的一篇文章中&#xff0c;我写过学习任何主题或领域基础知识的重要性。我建议你先阅读它&#xff08;如果你还没有&#xff09;&#xff0c;以便完全理解这篇文章。 如果您已经…

让人工智能解数学题,可能没你想象的那么简单

来源&#xff1a;微软研究院AI头条&#xff0c;授权CSDN发布。 欢迎人工智能领域技术投稿、约稿、给文章纠错&#xff0c;请发送邮件至heyccsdn.net 约1500年前的古代数学著作《孙子算经》中记载了一个有趣的问题&#xff1a;“今有雉兔同笼&#xff0c;上有三十五头&#xff0…

给自己的课程打个广告

给自己的一些付费课程打个广告吧&#xff0c;金额不高&#xff0c;但你们的支持可以让我在写作、分享时更有动力&#xff0c;在媳妇面前也更有地位哈哈&#xff0c;谢谢支持了&#xff01;&#xff01; 有问题欢迎留言或者加我微信: sxkejinet 面试经验分享OkHttp3 和 Retrofit…

大学生个人职业生涯规划书PPT

大学生如何职业生涯规划主要是指根据个人的兴趣、性格特点、内在潜能来确立个人的职业发展目标&#xff0c;并根据自身情况对未来职业生涯上的短期目标、中期目标和长期目标进行设定&#xff0c;根据设定的这些目标来规划不同阶段下需要完成自我提升的通道。简而言之就是自身通…

python职业规划书_大学生职业规划书

职业生涯规划&#xff08;简称生涯规划&#xff09;&#xff0c;又叫职业生涯设计&#xff0c;是将个人与组织相结合&#xff0c;在对一个人职业生涯的主客观条件进行测定、分析、总结的基础上&#xff0c;对自己的兴趣、爱好、能力、特点进行综合分析与权衡&#xff0c;结合时…

计算机相关专业的学生如何规划自己的职业?

一、 前言 2017年曾经写过一篇关于学什么编程方向的文章&#xff0c;当时反响很大&#xff0c;有不少在校的社团组织私下授权转载我的文章。现在的大学&#xff0c;两极分化极其严重&#xff0c;优秀的同学毕业找工作顺风顺水&#xff0c;平庸甚至较差的同学&#xff0c;找工作…

大学生职业规划策划书

一.前言 我时常问自己“人生之路到底该如何去走”&#xff0c;长久以来我也不断思考并在实践中体会这个问题。心中记得这样一句话“走好每一步&#xff0c;这就是你的人生。”人生之路其实十分短暂&#xff0c;因为你度过的每一天或者每一秒就是你的人生。正因为人生经不起虚度…

大学生职业生涯规划的意义

前言职业生涯规划是指个人发展与组织发展相结合&#xff0c;通过对职业生涯的主客观因素分析、总结和测定&#xff0c;确定一个人的奋斗目标&#xff0c;并为实现这一事业职业目标&#xff0c;而预先进行生涯系统安排的过程。在任何社会、任何体制下&#xff0c;个人职业设计更…

职业生涯规划(career planning)

本文转自&#xff1a;WIKI智库&#xff08;https://wiki.mbalib.com/wiki/职业生涯规划&#xff09; 职业生涯规划的定义 职业生涯规划&#xff08;简称生涯规划&#xff09;&#xff0c;又叫职业生涯设计&#xff0c;是指个人与组织相结合&#xff0c;在对一个人职业生涯的主…

计算机个人职业生涯规划

个人职业生涯规划 摘要 在当下竞争激烈的时代&#xff0c;如果没有做好充分的准备就去迎接社会的毒打&#xff0c;往往是遍体鳞伤。而一个人的职业规划将是我们面对社会的最好的铠甲&#xff0c;即使是简单的未来规划&#xff0c;也会使你成长的路上少点磕绊&#xff0c;所以…