移动支付文档中心:https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1
SDK下载地址: https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1
软件发布一年了,SDK更新了,那么你的软件也要跟着更新。
注意如果开发平台有集成流程,就按照开发平台的集成流程做就行了。按照集成流程详解去做,集成流程详解去做
-------------------------------------------------------------------------------------------------------------------------------------------------------------
本例讲三个例子:
1:运行支付宝的alipay_demo,
2:拷贝文件的方式调用支付宝
3:将支付宝变成model调用。
接入之前准备工作包括商户签约和密钥配置,
第一个例子:运行支付宝的alipay_demo
将alipay_demo导入Android Studio,选择Import project fromEclipse
这个时候有一个东西需要更新的,如下图所示
把上面的括号里面删除了,可以直接删除也可以通过f4,把Dependencies 里面的删除掉。 里面是 libs/alipaySdk-20160120.jar libs/android-support-v13.jar
修改为:
--------------------------- 在gradle里面添加
compile fileTree(dir: 'libs', include: ['*.jar'])
这个时候运行以后,点击“支付”按钮会显示
警告:PARTNER|RSA_PARIVATE|SELLER,原因是:
公钥,上传给服务器,服务器就认可这台电脑私钥加密的东西。
在PayDemoActivity:里面有。
下面的几个是公司给的或者是你帮公司申请的。
// 商户PID
public static final String PARTNER = "";
// 商户收款账号
public static final String SELLER = "";
// 商户私钥,pkcs8格式
public static final String RSA_PRIVATE = "";
// 支付宝公钥
暂时可以用的一个测试信息:2088其实就是阿里巴巴。
// 商户合作ID 必须以 2088 开头
public static final String
PARTNER = "2088601082136243";??// 收款人,支付宝账号 账号是固定的,一个商户一个账号?
public static final String
SELLER = "
[email protected] ";??// 客户端使用的私钥,对于请求进行数字签名,传给服务器,服务器使用公钥进行验证?
public static final String
RSA_PRIVATE = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM62H9NVaAFL54uyqjNv11J7eeOsh/xRQ2c31zUXGmFvuq5iUVxahQBNKa5O3w4qoOdzCt6yw+Fcl9hN/9NV9pWiCUBzNBluUMyqTb2Qs+bULisevBk810Uevo/Cct+gu+6e2tTal2dXszAXK7tYjJqd5Rzmc/qJRzFPNn4j3W2NAgMBAAECgYEAwEDBHtPrNHF9O/+Cru5RLGSs++SmYTTPZLuZy8XeAkthK/lDRIrn8lzR7E1sxYc+OaVUscU/y2VL0KDS06K6/8gVCcJe4UiCjIBXyhmwNBKBHf4jlKKAlaWZkPwJSxpfE1O16epBvTHZdyEY0ALfMnvQlUZ8RAAXo5DHGutHscECQQD++08BYfWDhYVpDzlEcPM+9fyecen8vGiX/T0+LB88kREIldjiQmqJyBvKECRBUJYg+2mqHGQjQMfBHfaaUsC9AkEAz4l27Qps5e93EmNlDn3RsMH+JVzMu0442nA8SbpRJOtmuqYDZAH7W2uj3J3J1gIbZg5zCxQc9rLDYcq2wo21EQJBAK1x/ZgPLpa8qLeCZ44q1wwpACI3ktccwnlBBfvYv5bPhyqz48hlLVt0B5M3z7GuQ7FD0+inT2a7liXDYBAx4nECQD8SSsc9LN0wSmKXPGYMDMcIHcGjE0E1Q4f3JgtOCU0MEVtWCp/BDm+5JcJtXaKhX0xDxeivAyJiL4ivv50ezdECQHptoOYG0tMCHL0oOXrZXsdpAFL/c8vX25Oq/uaYaR+Zgv02ipt+81YQ+8nYTwD55TZytt0TcifqUQhDf0y7XyQ=";
//注意了上面的这个RSA_PRIVATE 一定不能换行
支付宝一定要了解的内容
1:支付宝支付时候的签名机制:和oAuth 有很大的关系,有可能面试的时候可能会遇到 2:支付宝客户端错误码 3:Android 中PayTask 内部的参数orderInfo 必须要看 4:提交请求时的notify_url:让支付宝完成支付或者为完成支付的时候给商家服务器的
支付宝支付需要三个子系统:客户端,支付宝的服务器,商家(客户端自身的)服务器
9件以上85折,
注意这些都是服务器端计算的,而不是可以客户端计算.我之前写的订餐软件是在客户端计算的。
客户端下订单,服务器算好价格,客户端支付.
如果订单是100元,而我支付的是1块钱,怎么办呢? 这个是不是bug的部分呢?
首先客户端下一个订单
服务器告诉我需要1000元钱,
客户端交1000元,给支付宝服务器
支付宝服务器返回已经扣款或者失败.
支付宝服务器告诉商家后台某一个订单已经支付成功了
2:将支付宝的demo内容拷贝到现有的项目工程中,最好的方法还是第三种方法,因为第三种方法不用我们自己去申请权限了。
新建一个项目
在布局文件中:添加一个button “下订单”
下订单(从服务器获取订单信息,订单号,金额,打折信息,描述信息,然后将这里面的一些信息传送给支付宝,特别是订单号)
ali的libs 里面有jar包
把com 拷贝过来.
把res 里面的拷贝过来.跳过string
清单文件的操作:
权限
拷贝清单文件中activity内容到
android:name="com.alipay.sdk.pay.demo.PayDemoActivity"
android:icon="@drawable/msp_icon"
android:label="@string/app_name" >
android:name="com.alipay.sdk.pay.demo.H5PayDemoActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation|screenSize"
android:exported="false"
android:screenOrientation="behind"
android:windowSoftInputMode="adjustResize|stateHidden" >
在button 上面添加事件
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="btnAliPay"
android:text="支付宝支付"/>
public class OrderPayActivity extends AppCompatActivity {
private long mOrderNumber;
private float mTotalFee;
private String mOrderDes;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_pay);
Intent intent = getIntent();
mOrderNumber=intent.getLongExtra("orderNumber",0);
mTotalFee=intent.getFloatExtra("totalFee", 0);
mOrderDes=intent.getStringExtra("orderDes");
}
public void btnAliPay(View view) {
//开始 支付宝 支付
Intent intent = new Intent(this, PayDemoActivity.class);
startActivity(intent);
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 下订单,从服务器获取订单信息,订单号,金额,打折信息,描述信息
* @param view
*/
public void btnOrder(View view) {
//TODO, 下订单 ,跳转到支付 界面
//模拟 订单号 ,从护短服务器返回来的
long orderNumber = 1000000000;
//总 金额
float totalFee = 100f;
String orderDes ="您的订单 我们已经收到了 ";
Intent intent = new Intent(this,OrderPayActivity.class);
intent.putExtra("orderNumber",orderNumber);
intent.putExtra("totalFee",totalFee);
intent.putExtra("orderDes",orderDes);
startActivity(intent);
}
}
在PayDemoActivity 里面,注意里面的TODO的项目,就是修改的地方
package com.alipay.sdk.pay.demo;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import com.alipay.sdk.app.PayTask;
import com.example.kodulf.myshoppay.R;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
public class PayDemoActivity extends FragmentActivity {
// 商户 PID
public static final String PARTNER = "" ;
// 商户收款账号
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 ;
public static final String NOTIFY_URL_MUST_SET = "http://notify.msp.hk/notify.htm" ;
/**
* TODO 用于支付宝处理之后的结果
*/
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what ) {
case SDK_PAY_FLAG : {// TODO 处理支付处理之后的 操作
// TODO 用于解析支付宝服务器 反悔的支付结果的 JSON
PayResult payResult = new PayResult((String) msg.obj );
/**
* 同步返回的结果必须放置到服务端进行验证(验证的规则请看 https://doc.open.alipay.com/doc2/
* detail.htm?spm=0.0.0.0.xdvAU6&treeId=59&articleId=103665&
* docType=1) 建议商户依赖异步通知
*/
String resultInfo = payResult.getResult();// 同步返回需要验证的信息
String resultStatus = payResult.getResultStatus();
// 判断 resultStatus 为 “9000” 则代表支付成功,具体状态码代表含义可参考接口文档
if (TextUtils.equals (resultStatus, "9000" )) {
Toast.makeText (PayDemoActivity.this , " 支付成功 " , Toast.LENGTH_SHORT ).show();
} else {
// TODO 需要考虑支付成功之后,界面跳转到哪里?
// 判断 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 ;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.pay_main );
}
/**
* call alipay sdk pay. 调用 SDK 支付
* TODO 支付按钮的 点击事件。这个就是之前的 警告
*/
public void pay(View v) {
if (TextUtils.isEmpty (PARTNER ) || TextUtils.isEmpty (RSA_PRIVATE ) || TextUtils.isEmpty (SELLER )) {
new AlertDialog.Builder(this ).setTitle(" 警告 " ).setMessage(" 需要配置 PARTNER | RSA_PRIVATE| SELLER" )
.setPositiveButton(" 确定 " , new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
//
finish();
}
}).show();
return ;
}
// TODO orderInfo 是参考官方 开发 文档 ,组装成的 类似于 key=value&key=value 这种形式
// TODO 也是关键的 支付信息;包含订单号,总金额,购买的商品信息等等 ;
// TODO 下面添加了订单号这个参数
//String orderInfo = getOrderInfo(," 测试的商品 ", " 该测试商品的详细描述 ", "0.01");
String orderInfo = getOrderInfo(" 订单号 " ," 测试的商品 " , " 该测试商品的详细描述 " , "0.01" );
/**
* TODO 对订单做 RSA 签名 ,此处 是针对 orderInfo 来惊醒数字签名的,数字签名能够保证 orderInfo 不被非法修改。
* TODO 同时,因为 支付宝服务器保存了 商家的 公钥 ,签名 使用 私钥,这样就能保证 支付宝认可这个支付信息。
* TODO 如果私钥不匹配 ,那么支付宝是不会惊醒 真正的支付的 。
* TODO 反悔的是签名,不是整个信息
* 特别注意,这里的签名逻辑需要放在服务端,切勿将私钥泄露在代码中!
*/
String sign = sign(orderInfo);
try {
/**
* 仅需对 sign 做 URL 编码
*/
sign = URLEncoder.encode (sign, "UTF-8" );
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
/**
* 完整的符合支付宝参数规范的订单信息
* TODO 真正进行支付 API 调用的时候,就是使用这个 payInfo 来进行的;(更加正规和安全的 操作应该由服务器来生成,而不该是客户端来生成的)
*/
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 , true );
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();
}
/**
* 原生的 H5 (手机网页版支付切 natvie 支付) 【对应页面网页支付按钮】
*
* @param v
*/
public void h5Pay(View v) {
Intent intent = new Intent(this , H5PayDemoActivity.class );
Bundle extras = new Bundle();
/**
* url 是测试的网站,在 app 内部打开页面是基于 webview 打开的, demo 中的 webview 是 H5PayDemoActivity ,
* demo 中拦截 url 进行支付的逻辑是在 H5PayDemoActivity 中 shouldOverrideUrlLoading 方法实现,
* 商户可以根据自己的需求来实现
*/
String url = "http://m.taobao.com" ;
// url 可以是一号店或者美团等第三方的购物 wap 站点,在该网站的支付过程中,支付宝 sdk 完成拦截支付
extras.putString("url" , url);
intent.putExtras(extras);
startActivity(intent);
}
/**
* create the order info. 创建订单信息
* TODO 修改添加订单号
*/
//private String getOrderInfo(String subject, String body, String price) {
private String getOrderInfo(String orderNumber,String subject, String body, String price) {
// 签约合作者身份 ID
String orderInfo = "partner=" + " \" " + PARTNER + " \" " ;
// 签约卖家支付宝账号
orderInfo += "&seller_id=" + " \" " + SELLER + " \" " ;
// TODO 商户网站唯一订单号
//orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\"";
orderInfo += "&out_trade_no=" + " \" " + getOutTradeNo() + " \" " ;
// 商品名称
orderInfo += "&subject=" + " \" " + subject + " \" " ;
// 商品详情
orderInfo += "&body=" + " \" " + body + " \" " ;
// 商品金额
orderInfo += "&total_fee=" + " \" " + price + " \" " ;
// TODO 服务器异步通知页面路径
// TODO 非常重要。。告诉商家的后台,一定要通过这个 notify_url 来通知商家的后台支付成功了还是失败了。
// TODO Ctrl+Alt+c 设置 NOTIFY_URL_MUST_SET
orderInfo += "¬ify_url=" + " \" " + NOTIFY_URL_MUST_SET + " \" " ;
// 服务接口名称, 固定值
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 。
// TODO 30 分钟之内支付
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. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
*
*/
private 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
* 待签名订单信息
*/
private String sign(String content) {
return SignUtils.sign (content, RSA_PRIVATE );
}
/**
* get the sign type we use. 获取签名方式
*
*/
private String getSignType() {
return "sign_type= \" RSA \" " ;
}
}
把PayDemoActivity 里面的内容拷贝过来.
https://doc.open.alipay.com/doc2/alipayDocIndex.htm
入驻开放平台
https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.62LBHX&treeId=44&articleId=103240&docType=1
RSA私钥及公钥生成
https://doc.open.alipay.com/doc2/detail?treeId=44&articleId=103242&docType=1
----------------
下午:
支付宝的密钥
C:\2016notpatupdate\161217\WS_MOBILE_PAY_SDK_BASE\支付宝钱包支付接口开发包2.0标准版(20160120)\DEMO\openssl\bin
双击openssl.exe
C:\2016notpatupdate\161217\WS_MOBILE_PAY_SDK_BASE\支付宝钱包支付接口开发包2.0标准版(20160120)\DEMO\openssl
里面的 生成命令 文件里面的东西执行
RSA密钥生成命令
生成RSA私钥
openssl>genrsa -out rsa_private_key.pem 1024
生成RSA公钥
openssl>rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
将RSA私钥转换成PKCS8格式
openssl>pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
注意:“>”符号后面的才是需要输入的命令。
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMrHDwvx4+RV+RJm
tdE1ckR43qysiNjaxbIenZkhArYC5Rjla2l3jdxBWx/Xh0tcU6cfGgnmmkGq3RD2
ZUpUGgfKThcmR/QO0f+qVAUoC04K+Y9LSBRahqAnMIjFUcEnyBiwpZdfanH2xXII
gtDRrgYmVC2ySjw/tpmrU5mzVzt9AgMBAAECgYEAqYDyS/rclB9lwAMJkyNJLIGZ
KeBj2FowDe/Xr4xPltQeq8wDGLtuYyJiyOBCYTWBW978xi/03FW2y5ocG6DnzAM2
fVpnXV0V6hSakyFTxc+IiIaq8hglmNEfyQ4Fq9j7c/+vECCxBIrYlaoGPg2Aoagr
Ta1pCGXChYrOubrIdAECQQD2Voi11thvqFDPUkp2SLE9B5ctSfo4Br+nYtguKv35
rlmFovl6Ck4mB5J2fHWhuKHW42byv6Z8oUvb600XvjJ9AkEA0rsjAzUfNV6wGcto
N3kvb8J2oLxatdSsTaZ0YUS+sOL4WvbN6q2/aY6VxGQDAmTPG4rmKBr4wpj8t+fe
gVp9AQJABWTRq4GfzZoW4uM/ZCWlU9vFsKUtCGsFaUndx+0DEKODrExsQALXwTdr
OpLxFHBxgr4J9AjEQXhaq98UGg/9FQJBAJe4lqfLinGxf9bChYFTJh0wBJsLob/C
pF+v1aDmjujqMWfExFMPz32fZCMm4qfJjvfElJsReEMbRPDf52p4jQECQQCihMBg
7fPijmGiOhsp6ZSCc02jj9loKpKS0ePAGWArHnTwJURtaxLtaPVFD/bWBetC6Cs5
cleVdEXb/sVuuctt
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
第三种 方法 支付宝导成模块的形式.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
新建一个工程:
注意要选择no activity.
File->New->Model->Android Library
AlipayModule.
app 和model 两个模块,app 是要不好导入到其他的文件里面对俄。
先拷java
然后res
然后清单文件。
lib 文件
R文件
拷贝权限和application:
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:resizeable="true"
android:smallScreens="true" />
android:allowBackup="true"
android:label="@string/app_name"
android:theme="@android:style/Theme.Light.NoTitleBar" >
android:name="com.alipay.sdk.pay.demo.PayDemoActivity"
android:icon="@drawable/msp_icon"
android:label="@string/app_name" >
android:name="com.alipay.sdk.pay.demo.H5PayDemoActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation|screenSize"
android:exported="false"
android:screenOrientation="behind"
android:windowSoftInputMode="adjustResize|stateHidden" >
直接 导入 上面的这个 模块就行了。
在app 里面提哦安家一个行的
添加上类库的依赖 就可以直接使用了。然后直接调用刚才我们新建的model 里面的
添加一个button 然后button 直接
Intent intent = new Intent(this,PayDemoActivity.class);
startActivity(intent);
如果抛出一场把model里面payDemoActiviyt样式删除
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
用模块的形式优点:activity 不需要配置,权限不需要配置了。
PS:企业必须要有30万的余额
支付宝实名认证流程查看更多申请帮助 企业账户认证,您需要准备以下材料:查看申请流程 营业执照; 申请人的有效身份证信息; 提交申请人如非法定代表人需提供企业委托授权书; 银行对公账户; 个人账户认证,您需要准备以下材料:查看申请流程 申请人身份证彩色照片或彩色扫描件(正反面都需要); 申请人的银行账户;
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
支付相关文档,里面有银联支付,还有两个图片需要注意的。
移动支付文档中心:
2:https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1
SDK下载地址:
3: https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1