Android端集成支付宝支付

十年热恋 提交于 2019-11-27 04:24:21

Android端集成支付宝支付

1.申请账号及配置变量

支付宝快速接入链接点击打开链接


支付宝扫码或者账号密码登录

下面是支付宝给出的接入介绍

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


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

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

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

第二步:配置应用

添加app支付功能

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

开始添加

签约

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

开始签约

2、密钥包含:

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

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

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

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

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

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


开始集成和开发前

在开始集成和开发前,首先了解一下常用的接入方式和架构建议:

其次,为了保证交易安全,支付宝采用了一系列的安全手段:

  1. 采用HTTPS协议传输交易数据,防止数据被截获,解密。

  2. 采用RSA非对称密钥,明确交易双方的身份,保证交易主体的正确性和唯一性

了解更多的安全设计指南

如何集成客户端SDK

在集成App支付能力时,提供主流移动平台的App提供集成方式。

下载客户端SDK

更多集成说明参见客户端集成说明。

如何集成服务端SDK

为了帮助开发者调用开放接口,我们提供了开放平台服务端DEMO&SDK,包含JAVA、PHP和.NET三语言版本,封装了签名&验签、HTTP接口请求等基础功能(下单请求参数orderStr在服务端SDK封装,客户端SDK直接使用)。强烈建议先下载对应语言版本的SDK并引入您的开发工程进行快速接入。

SDK调用前需要进行初始化,代码示例如下:

AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE); 

关键参数说明:

配置参数示例值解释获取方式/示例值
URL支付宝网关(固定)https://openapi.alipay.com/gateway.do
APP_IDAPPID即创建应用后生成获取见上面创建应用并获取APPID
APP_PRIVATE_KEY开发者应用私钥,由开发者自己生成获取见上面配置密钥
FORMAT参数返回格式,只支持jsonjson(固定)
CHARSET请求和签名使用的字符编码格式,支持GBK和UTF-8开发者根据实际工程编码配置
ALIPAY_PUBLIC_KEY支付宝公钥,由支付宝生成获取详见上面配置密钥
SIGN_TYPE商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2RSA2

接下来,就可以用alipayClient来调用具体的API了。alipayClient只需要初始化一次,后续调用不同的API都可以使用同一个alipayClient对象。

TIPS:App支付不支持第三方授权,不能代商家发起请求。

第四步:调用接口

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

系统交互流程:

如图,以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来调用。

交易操作

1.交易查询接口alipay.trade.query:

AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2"); //获得初始化的AlipayClient AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();//创建API对应的request类 request.setBizContent("{" + "   \"out_trade_no\":\"20150320010101001\"," + "   \"trade_no\":\"2014112611001004680073956707\"" + "  }");//设置业务参数 AlipayTradeQueryResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类 System.out.print(response.getBody()); //根据response中的结果继续业务逻辑处理 

关键入参:

参数名称参数说明
out_trade_no支付时传入的商户订单号,与trade_no必填一个
trade_no支付时返回的支付宝交易号,与out_trade_no必填一个

关键出参:

参数名称参数说明
trade_no支付宝28位交易号
out_trade_no支付时传入的商户订单号
trade_status交易当前状态

2.交易退款接口alipay.trade.refund:
商户由于业务原因如金额错误、用户退货、对账不平等情况可能需要退款,退款的途径按照支付途径原路返回。支付渠道为花呗、余额等退款即时到账。银行卡的退款时间以银行退款时间为准,一般情况下2小时内可到账。可在商户门户(b.alipay.com)中退款;也可使用交易成功的商户订单号或支付宝交易号进行退款 , 支持全额和部分退款,其过程如下图所示:


退款接口调用示例如下:
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2"); //获得初始化的AlipayClient AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();//创建API对应的request类 request.setBizContent("{" + "    \"out_trade_no\":\"20150320010101001\"," + "    \"trade_no\":\"2014112611001004680073956707\"," + "    \"out_request_no\":\"1000001\"," + "    \"refund_amount\":\"1\"" + "  }");//设置业务参数 AlipayTradeRefundResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类 System.out.print(response.getBody()); // 根据response中的结果继续业务逻辑处理 

关键入参:

参数名称参数说明
out_trade_no支付时传入的商户订单号,与trade_no必填一个
trade_no支付时返回的支付宝交易号,与out_trade_no必填一个
out_request_no本次退款请求流水号,部分退款时必传
refund_amount本次退款金额

关键出参:

参数名称参数说明
refund_fee该笔交易已退款的总金额

3.查询对账单下载地址接口alipay.data.dataservice.bill.downloadurl.query:
为了保障交易的正确性,支付宝提供了交易账单数据提供给商户对账,对账说明

AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2"); //获得初始化的AlipayClient AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();//创建API对应的request类 request.setBizContent("{" + "    \"bill_type\":\"trade\"," + "    \"bill_date\":\"2016-04-05\"" + "  }");//设置业务参数 AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request); System.out.print(response.getBody()); //根据response中的结果继续业务逻辑处理 

关键入参:

参数名称参数说明
bill_type固定传入trade
bill_date需要下载的账单日期,最晚是当期日期的前一天

关键出参:

参数名称参数说明
bill_download_url账单文件下载地址,30秒有效

下载账单文件:

//将接口返回的对账单下载地址传入urlStr String urlStr = "http://dwbillcenter.alipay.com/downloadBillFile.resource?bizType=X&userId=X&fileType=X&bizDates=X&downloadFileName=X&fileId=X"; //指定希望保存的文件路径 String filePath = "/Users/fund_bill_20160405.csv"; URL url = null; HttpURLConnection httpUrlConnection = null; InputStream fis = null; FileOutputStream fos = null; try {     url = new URL(urlStr);     httpUrlConnection = (HttpURLConnection) url.openConnection();     httpUrlConnection.setConnectTimeout(5 * 1000);     httpUrlConnection.setDoInput(true);     httpUrlConnection.setDoOutput(true);     httpUrlConnection.setUseCaches(false);     httpUrlConnection.setRequestMethod("GET");     httpUrlConnection.setRequestProperty("Charsert", "UTF-8");     httpUrlConnection.connect();     fis = httpUrlConnection.getInputStream();     byte[] temp = new byte[1024];     int b;     fos = new FileOutputStream(new File(filePath));     while ((b = fis.read(temp)) != -1) {         fos.write(temp, 0, b);         fos.flush();     } } catch (MalformedURLException e) {     e.printStackTrace(); } catch (IOException e) {     e.printStackTrace(); } finally {     try {         fis.close();         fos.close();         httpUrlConnection.disconnect();     } catch (NullPointerException e) {         e.printStackTrace();     } catch (IOException e) {         e.printStackTrace();     } } 

第五步:调试应用

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

第六步:上线应用

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




支付宝扫码或者账号密码登录

点击开发接入



鼠标放到支付应用上点击查看接入文档


点击全部文档选择APP支付


点击下载SDK及Demo


2.配置项目

第一步:将Demo中libs 文件夹下面的支付宝jar导入到as里并依赖到项目里

根据上面的链接及方法  创建自己的应用拿到APPID,设置自己的公钥及私钥,签约。

公钥是传给支付宝后台的,私钥是作为参数传给自己项目后台的。

第二步:

配置AndroidManifest.xml文件。此文件大都是配置信息的。如果手机里没有支付宝app的话就会跳到H5界面登录支付。

<!-- alipay sdk begin --> <activity   android:name="com.alipay.sdk.app.H5PayActivity"   android:configChanges="orientation|keyboardHidden|navigation"   android:exported="false"   android:screenOrientation="behind"   android:windowSoftInputMode="adjustResize|stateHidden" > </activity>

可以看到的是这是一个Activity.配置文件。就如平常的注册Activity 一样,放在application节点之中即可。下面是权限的配置:

<uses-permission android:name="android.permission.INTERNET" />     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />     <uses-permission android:name="android.permission.READ_PHONE_STATE" />     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

这是必要的权限,如果添加过的,就不需要重新添加了。没有的,则需要添加到里面。


第三步:

下面就是主要Activity的代码的引入了。主要代码如下:

public static final String PARTNER = "注册账户的PID";   // 商户收款账号   public static final String SELLER = "支付宝收款账户";   // 商户私钥,pkcs8格式   public static final String RSA_PRIVATE = "商户私钥";   // 支付宝公钥   public static final String RSA_PUBLIC = "支付宝公钥";    private static final int SDK_PAY_FLAG = 1;    private static final int SDK_CHECK_FLAG = 2;    private Handler mHandler = new Handler() {     public void handleMessage(Message msg) {       switch (msg.what) {       case SDK_PAY_FLAG: {         PayResult payResult = new PayResult((String) msg.obj);          // 支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签         String resultInfo = payResult.getResult();          String resultStatus = payResult.getResultStatus();          // 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档         if (TextUtils.equals(resultStatus, "9000")) {           Toast.makeText(PayDemoActivity.this, "支付成功",               Toast.LENGTH_SHORT).show();         } else {           // 判断resultStatus 为非“9000”则代表可能支付失败           // “8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)           if (TextUtils.equals(resultStatus, "8000")) {             Toast.makeText(PayDemoActivity.this, "支付结果确认中",                 Toast.LENGTH_SHORT).show();            } else {             // 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误             Toast.makeText(PayDemoActivity.this, "支付失败",                 Toast.LENGTH_SHORT).show();            }         }         break;       }       case SDK_CHECK_FLAG: {         Toast.makeText(PayDemoActivity.this, "检查结果为:" + msg.obj,             Toast.LENGTH_SHORT).show();         break;       }       default:         break;       }     };   };

这段代码,是一个Handler,放在Java 文件的顶部。

/**    * call alipay sdk pay. 调用SDK支付    *    */   public void pay() {     // 订单     String orderInfo = getOrderInfo("测试的商品", "该测试商品的详细描述", "0.01");      // 对订单做RSA 签名     String sign = sign(orderInfo);     try {       // 仅需对sign 做URL编码       sign = URLEncoder.encode(sign, "UTF-8");     } catch (UnsupportedEncodingException e) {       e.printStackTrace();     }      // 完整的符合支付宝参数规范的订单信息     final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"         + getSignType();      Runnable payRunnable = new Runnable() {        @Override       public void run() {         // 构造PayTask 对象         PayTask alipay = new PayTask(PayDemoActivity.this);         // 调用支付接口,获取支付结果         String result = alipay.pay(payInfo);          Message msg = new Message();         msg.what = SDK_PAY_FLAG;         msg.obj = result;         mHandler.sendMessage(msg);       }     };      // 必须异步调用     Thread payThread = new Thread(payRunnable);     payThread.start();   }    /**    * check whether the device has authentication alipay account.    * 查询终端设备是否存在支付宝认证账户    *    */   public void check(View v) {     Runnable checkRunnable = new Runnable() {        @Override       public void run() {         // 构造PayTask 对象         PayTask payTask = new PayTask(PayDemoActivity.this);         // 调用查询接口,获取查询结果         boolean isExist = payTask.checkAccountIfExist();          Message msg = new Message();         msg.what = SDK_CHECK_FLAG;         msg.obj = isExist;         mHandler.sendMessage(msg);       }     };      Thread checkThread = new Thread(checkRunnable);     checkThread.start();    }    /**    * get the sdk version. 获取SDK版本号    *    */   public void getSDKVersion() {     PayTask payTask = new PayTask(this);     String version = payTask.getVersion();     Toast.makeText(this, version, Toast.LENGTH_SHORT).show();   }    /**    * create the order info. 创建订单信息    *    */   public String getOrderInfo(String subject, String body, String price) {     // 签约合作者身份ID     String orderInfo = "partner=" + "\"" + PARTNER + "\"";      // 签约卖家支付宝账号     orderInfo += "&seller_id=" + "\"" + SELLER + "\"";      // 商户网站唯一订单号     orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\"";      // 商品名称     orderInfo += "&subject=" + "\"" + subject + "\"";      // 商品详情     orderInfo += "&body=" + "\"" + body + "\"";      // 商品金额     orderInfo += "&total_fee=" + "\"" + price + "\"";      // 服务器异步通知页面路径     orderInfo += "¬ify_url=" + "\"" + "http://notify.msp.hk/notify.htm"         + "\"";      // 服务接口名称, 固定值     orderInfo += "&service=\"mobile.securitypay.pay\"";      // 支付类型, 固定值     orderInfo += "&payment_type=\"1\"";      // 参数编码, 固定值     orderInfo += "&_input_charset=\"utf-8\"";      // 设置未付款交易的超时时间     // 默认30分钟,一旦超时,该笔交易就会自动被关闭。     // 取值范围:1m~15d。     // m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。     // 该参数数值不接受小数点,如1.5h,可转换为90m。     orderInfo += "&it_b_pay=\"30m\"";      // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付     // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";      // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空     orderInfo += "&return_url=\"m.alipay.com\"";      // 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)     // orderInfo += "&paymethod=\"expressGateway\"";      return orderInfo;   }    /**    * get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)    *    */   public String getOutTradeNo() {     SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss",         Locale.getDefault());     Date date = new Date();     String key = format.format(date);      Random r = new Random();     key = key + r.nextInt();     key = key.substring(0, 15);     return key;   }    /**    * sign the order info. 对订单信息进行签名    *    * @param content    *            待签名订单信息    */   public String sign(String content) {     return SignUtils.sign(content, RSA_PRIVATE);   }    /**    * get the sign type we use. 获取签名方式    *    */   public String getSignType() {     return "sign_type=\"RSA\"";   }  }
这一段代码要和上一段代码放在一个Java 文件中,需要注意的一个方法是。 pay() 方法和getOrderInfo(); 需要注意的是,在我们选择支付宝支付的按钮中调用的 是 pay() 方法。而放在pay()方法中则需要调用getOrderInfo(),仔细发现,getOrderInfo()方法里面的三个参数。其中price 参数就是我们要消费的金额,当我们调用pay()方法的时候,就需要传入一个price 的参数,就是我们需要支付的金额。具体的金额怎么传入,计算,要根据项目需要来自己获取了,这样项目集成支付宝就圆满结束了。

配置的具体操作:

在PayDemoActivity中配置几个变量:

  1. //PID  
  2. public static final String PARTNER = "";  
在这里填上我们上面找到的PID;
  1. // 商户收款账号  
  2. public static final String SELLER = "76949XXXX@qq.com";  
然后在SELLER上写上我们支付宝的登录帐户,即那个你申请移动支付的支付宝账号
  1. // 支付宝公钥  
  2. public static final String RSA_PUBLIC ="";  
然后在RSA_PUBLIC这里填上支付宝公钥
  1. // 商户私钥,pkcs8格式  
  2. public static final String RSA_PRIVATE = "";  
最后是填上RSA_PRIVATE对应的商户私钥,注意是PKCS8格式的。
私钥这部分,注意是----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----之间的部分,即那段纯代码,不要把----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----给复制进去了。中间的这部分就是公钥。

现在运行demo就直接可以支付了。

3、代码讲解

通过上面的配置,demo应该就直接可以运行了,但这里所涉及的代码,我们再仔细看看
主要的支付与结果返回就是pay()这个函数,这里完成了支付所需要的所有功能。代码如下:

  1. public void pay(View v) {  
  2.     …………  
  3.     // 订单信息  
  4.     String orderInfo = getOrderInfo("测试的商品""该测试商品的详细描述""0.01");  
  5.   
  6.     // 对订单做RSA 签名  
  7.     String sign = sign(orderInfo);  
  8.     try {  
  9.         // 仅需对sign 做URL编码  
  10.         sign = URLEncoder.encode(sign, "UTF-8");  
  11.     } catch (UnsupportedEncodingException e) {  
  12.         e.printStackTrace();  
  13.     }  
  14.   
  15.     // 完整的符合支付宝参数规范的订单信息  
  16.     final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"  
  17.             + getSignType();  
  18.   
  19.     Runnable payRunnable = new Runnable() {  
  20.   
  21.         @Override  
  22.         public void run() {  
  23.             // 构造PayTask 对象  
  24.             PayTask alipay = new PayTask(PayDemoActivity.this);  
  25.             // 调用支付接口,获取支付结果  
  26.             String result = alipay.pay(payInfo);  
  27.   
  28.             Message msg = new Message();  
  29.             msg.what = SDK_PAY_FLAG;  
  30.             msg.obj = result;  
  31.             mHandler.sendMessage(msg);  
  32.         }  
  33.     };  
  34.   
  35.     // 必须异步调用  
  36.     Thread payThread = new Thread(payRunnable);  
  37.     payThread.start();  
  38. }  

这里总是分了四步来完成支付与结果接收。

第一步:构造定单信息:

  1. String orderInfo = getOrderInfo("测试的商品""该测试商品的详细描述""0.01");  
主要是这句,即在getOrderInfo()函数中完成定单信息的构造:(这里对getOrderInfo函数做的精减,更多字段及意义参考源码)

有关paymethod的方法使用,参考:https://cshall.alipay.com/support/help_detail.htm?help_id=476935
各个字段的意义及取值参考:http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103663&docType=1

  1. public String getOrderInfo(String subject, String body, String price) {  
  2.   
  3.     // 签约合作者身份ID  
  4.     String orderInfo = "partner=" + "\"" + PARTNER + "\"";  
  5.   
  6.     // 签约卖家支付宝账号  
  7.     orderInfo += "&seller_id=" + "\"" + SELLER + "\"";  
  8.   
  9.     // 商户网站唯一订单号  
  10.     orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\"";  
  11.   
  12.     // 商品名称  
  13.     orderInfo += "&subject=" + "\"" + subject + "\"";  
  14.   
  15.     // 商品详情  
  16.     orderInfo += "&body=" + "\"" + body + "\"";  
  17.   
  18.     // 商品金额  
  19.     orderInfo += "&total_fee=" + "\"" + price + "\"";  
  20.   
  21.     // 服务器异步通知页面路径  
  22.     orderInfo += "&notify_url=" + "\"" + "http://notify.msp.hk/notify.htm"  
  23.             + "\"";  
  24.   
  25.     …………  
  26.     return orderInfo;  
  27. }  
这里就是通过我们的提供的商家ID,产品信息,价格等信息来构造定单及回调页面,这里需要非常注意的一个地方:
  1. // 服务器异步通知页面路径  
  2. orderInfo += "&noify_url=" + "\"" + "http://notify.msp.hk/notify.htm"  
  3.         + "\"";  
服务器异步通知页面路径,首先我们用支付宝支付之后,支付宝会返回给我们两个通知,一个是同步的,就是我们点击支付后支付宝直接反馈给我们客户端的信息,我们可以直接拿到,根据反馈的结果可以初步判定该次交易是否成功,第二个就是服务器异步的通知,这个异步的通知是支付宝的服务器端发给我们服务器端的信息,我们在客户端是直接获取不了的,那支付宝的服务器怎么知道我们服务器的路径呢,那就是这参数的作用了,我们给支付宝服务器一个路径,它就会在订单状态改变的时候给我们服务器端一个反馈,告诉服务器这次交易的状态,如果服务器结果判定该次交易成功了,就必须返给支付宝服务器一个success,要不服务器会一直给我们异步通知,因为它不知道该次交易是否完成了(一般情况下25小时内8次通知,频率一般是2m 10m 10m 1h 2h 6h 15h),我们一般会在收到异步通知时,对订单的状态进行更新。
其它的就不讲了,通过看源码都能看得懂,比如构造订单号啥的。

第二步:对订单字符串做RSA签名

为什么要签名呢?当然是防止传输出错了,这可是跟钱相关的,如果orderInfo传输过程中出错了,那怎么样来校验它是不是出错了呢,只有通过签名算法来了。所以这里就需要对订单字符串做签名。
具体签名算法就不讲了,直接应用到项目中就行,不需要理解,如果想看看怎么实现的,里面有对应的源码,可以去研究一下。

  1. // 对订单做RSA 签名  
  2. String sign = sign(orderInfo);  
  3. try {  
  4.     // 仅需对sign 做URL编码  
  5.     sign = URLEncoder.encode(sign, "UTF-8");  
  6. catch (UnsupportedEncodingException e) {  
  7.     e.printStackTrace();  
  8. }  

第三步:构造完成的请求字符串

在订单字符串和签名做完以后,就可以用他们来构造完整的请求字符串了:
  1. // 完整的符合支付宝参数规范的订单信息  
  2. final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"  
  3.         + getSignType();  

第四步:请求与结果返回

最后是发送请求,代码如下:

  1. Runnable payRunnable = new Runnable() {  
  2.   
  3.     @Override  
  4.     public void run() {  
  5.         // 构造PayTask 对象  
  6.         PayTask alipay = new PayTask(PayDemoActivity.this);  
  7.         // 调用支付接口,获取支付结果  
  8.         String result = alipay.pay(payInfo);  
  9.   
  10.         Message msg = new Message();  
  11.         msg.what = SDK_PAY_FLAG;  
  12.         msg.obj = result;  
  13.         mHandler.sendMessage(msg);  
  14.     }  
  15. };  
  16.   
  17. // 必须异步调用  
  18. Thread payThread = new Thread(payRunnable);  
  19. payThread.start();  
最关键的部分在这里:
  1. PayTask alipay = new PayTask(PayDemoActivity.this);  
  2. // 调用支付接口,获取支付结果  
  3. String result = alipay.pay(payInfo);  
  4.   
  5. Message msg = new Message();  
  6. msg.what = SDK_PAY_FLAG;  
  7. msg.obj = result;  
  8. mHandler.sendMessage(msg);  
在String result = alipay.pay(payInfo);中,就直接获得了支付结果;
然后通过handler将结果发送出去。
这就是同步的方式获取支付结果的方式。
好了,有关支付宝对接的方法全部都在这了。至于getOrderInfo函数里,使用的调用银行卡支付,我觉得也没啥用,在我们程序里也没接上。

4.可能你会出现这些问题:

   接下来就是说一些支付宝支付遇到的问题,

   1.提示系统繁忙,请稍后再试(ALI69)你的商户idPARTNER有问题,

   2.提示系统繁忙,请稍后再试(ALI129)你的商户账号SELLER有问题,记住PARTNER与SELLER必须一致。

   3.提示系统繁忙,请稍后再试(ALI59)你支付的钱最低是0.01,不能写成0.00或其他负值。

   4.报如下错

  1. java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag  
  2. 01-19 09:17:15.373: W/System.err(24886):
  1. at org.apache.harmony.xnet.provider.jsse.OpenSSLRSAKeyFactory.engineGeneratePrivate(OpenSSLRSAKeyFactory.java:77)  
  2. 01-19 09:17:15.373: W/System.err(24886): 
  1. at java.security.KeyFactory.generatePrivate(KeyFactory.java:186)  
  2. 01-19 09:17:15.373: W/System.err(24886):
  1. at com.alipay.sdk.pay.demo.SignUtils.sign(SignUtils.java:20)  
  2. 01-19 09:17:15.373: W/System.err(24886):
  在SignUtils类里将KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);这句换成KeyFactory keyf = KeyFactory.getInstance(ALGORITHM,"BC");

 5、调用支付界面成功后,支付失败,检查是支付宝或支付宝绑定的银行卡是否有钱支付以及秘钥是否正确。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!