支付宝支付,使用及大范围难题

原文链接:
两行代码实现微信支付, 三行代码实现支付宝支付 —— 由Ethan2016分享

此项目已开源 赶快来围观 Start支持下吧

1,支付宝申请:https://b.alipay.com/order/productDetail.htm?productId=2013080604609654&tabId=4\#ps-tabinfo-hash 

第一步:引入依赖包gradle对应的项目中的build.gradle文件添加依赖:dependencies
{//添加支付库compile
‘io.github.mayubao:pay_library:1.0.0’}第二步:使用微信支付方式
步骤//1.创建微信支付请求WechatPayReq wechatPayReq = new
WechatPayReq.Builder().with //activity实例.setAppId
//微信支付AppID.setPartnerId(partnerid)//微信支付商户号.setPrepayId//预支付码–>包含支付的金额//
.setPackageValue(wechatPayReq.get)//”Sign=WXPay”.setNonceStr.setTimeStamp(timestamp)//时间戳.setSign//签名.create();//2.发送微信支付请求PayAPI.getInstance().sendPayRequest(wechatPayReq);//关于微信支付的回调//wechatPayReq.setOnWechatPayListener(new
OnWechatPayListener);使用支付宝支付方式
步骤//1.创建支付宝支付配置AliPayAPI.Config config = new
AliPayAPI.Config.Builder().setRsaPrivate(rsa_private) //设置私钥
(商户私钥,pkcs8格式).setRsaPublic(rsa_public)//设置公钥.setPartner
//设置商户.setSeller
//设置商户收款账号.create();//2.创建支付宝支付请求AliPayReq aliPayReq =
new
AliPayReq.Builder().with//Activity实例.apply//支付宝支付通用配置.setOutTradeNo(outTradeNo)//设置唯一订单号.setPrice//设置订单价格.setSubject(orderSubject)//设置订单标题.setBody(orderBody)//设置订单内容
订单详情.setCallbackUrl(callbackUrl)//设置回调地址.create()//.setOnAliPayListener;////3.发送支付宝支付请求PayAPI.getInstance().sendPayRequest(aliPayReq);//关于支付宝支付的回调//aliPayReq.setOnAliPayListener(new
OnAliPayListener);混淆方式

【客户端开源地址-JPay】【服务端端开源地址-在com.javen.alipay

2,开发文档:https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1 

-dontwarn io.github.mayubao.pay_library.**-keep class
io.github.mayubao.pay_library.** {*;}

包名下

3,载入aplipay库,关联类库

-dontwarn com.tencent.**-keep class com.tencent.** {*;}

4,用申请到的seller(商户支付宝号),partner(商户PID:2088***********),private
key(私钥RSA转码后的一串字符)连接支付宝服务器,生成订单,加密,签名,设置schema,设置服务器端的回调地址

-dontwarn com.alipay.**-keep class com.alipay.** {;}-dontwarn
com.ta.utdid2.
*-keep class com.ta.utdid2.** {;}-dontwarn
com.ut.device.
*-keep class com.ut.device.** {;}-dontwarn
org.json.alipay.
*-keep class corg.json.alipay.**
{*;}官方文档微信支付官方文档
支付流程
支付流程

上一篇详细介绍了微信APP支付点击这里

5,客户端支付成功,由支付宝客户端回调应用客户端,支付宝服务器回调系统后台服务器

此篇文章来详细介绍下支付宝APP支付

6,解决方法

目录

1、报错:rsa_private read error : private key is NULL

1、支付宝与微信对比(申请、费率、结算周期)

原因:私钥没有转成PKCS8

2、支付宝上线应用

1)、在RSADataSigner.m文件中搜索代码[result appendString:@”—–BEGIN
PRIVATE KEY—–\n”];将其改成[result appendString:@”—–BEGIN RSA
PRIVATE KEY—–\n”];

3、支付宝App支付Android集成流程详解

2)、在RSADataSigner.m文件中搜索代码[result appendString:@”\n—–END
PRIVATE KEY—–“];将其改成[result appendString:@”\n—–END RSA
PRIVATE KEY—–“];

4、服务端实现(建议直接官方提供的服务端SDK)

7,加密解密的过程:https://cshall.alipay.com/support/help\_detail.htm?help\_id=397433&keyword=%25C8%25E7%25BA%25CE%25C9%25FA ,是客户端生成的,

5、客户端实现

生成私钥命令:genrsa -out rsa_private_key.pem 1024

转换格式:OpenSSL> pkcs8 -topk8 -inform PEM -in
rsa_private_key.pem -outform PEM -nocrypt

生成公钥:OpenSSL> rsa -in rsa_private_key.pem -pubout -out
rsa_public_key.pem

6、常见错误解决方案(ALI40247、AL38173)

8,在RSA的签名时,需要私钥和公钥一起参与签名。私钥与公钥皆是客户通过OPENSSL来生成得出的。客户把生成出的公钥与支付宝技术人员配置好的支付宝公钥做交换。因此,在签名时,客户要用到的是客户的私钥及支付宝的公钥。

补充(20170513) 
支付宝APP支付可以使用沙箱环境测试。如需开启测试模式只需要在OnCreate中添加如下代码。沙箱环境测试APP支付中请使用沙箱版钱包测试:点击开发者中心-沙箱环境-沙箱工具

9,支付宝sdk集成,报系统繁忙请稍后再试(ALI64),公私钥不匹配,必须本机生成公钥私钥么

EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);

10,上传公钥:https://cshall.alipay.com/enterprise/help\_detail.htm?help\_id=473890 

必发365游戏官方网址 1

11,seller,partner:签约后,支付宝会为每个商户分配一个唯一的parnter和seller。

使用沙箱环境测试

12,公钥必须给支付宝,不然他们解密不了啊,然后支付宝返回数据再用支付宝的私钥加密,然后用支付宝给的公钥解密,o
my god.

1、支付宝与微信对比

公钥加密方法,对称,加密解密一样的,非对称,非对称就是加密和解密的不同规则,RSA代表三个贱人,

申请:【微信开发平台】注册的邮箱不能与腾讯其他产品同号,需要开发者资质认证(需要¥300,而且支付商户与公众号不公用)而支付宝只需要企业实名认证,其他质料类似(营业执照、组织机构代码(现在都三证合一了))。

13,先与支付宝签约,获得商户ID(partner)和账号ID(seller)

费率:

(这个主要是公司的负责),下载相应的公钥私钥文件(加密签名用),私钥文件不是下载的,2了吧,

【微信签约汇率参考质料】【支付宝签约汇率参考质料】

14,由服务器来生成订单,然后返回订单字符串:

结算周期:

NSString * dataString = [responseObject
valueForKeyNullReplace:@”data”];

微信结算周期:话费通讯、财经资讯、股票软件类、网络虚拟服务以及互联网相关行业
T+7  众筹 T+3
其他T+1,结算款项自动提现到商户的结算账户,一般从结算日起3个工作日到账(具体到账时间视不同银行到账情况而定)

int ret = [alixpay pay:dataString applicationScheme:appScheme];

支付宝结算周期:及时到支付宝账号

1,支付宝企业账户签约快捷支付获得商户id,账户id

2、支付宝上线应用

2,用openssl生成公钥,私钥,上传公钥,下载另外一个公钥

1、注册账号并实名认证

3,生成订单信息,设置回调URL,schema,用RSA加密,发起支付

注册账号了没有实名认证进入开发平台的管理中心会提示如下图

4,支付结果回调客户端,客户端处理,

必发365游戏官方网址 2

实名认证

必发365游戏官方网址 3

为什么要实名认证

【账户认证-商家认证流程介绍】

必发365游戏官方网址 4

商家认证流程

2、创建应用开通支付并上线

官方文档有详细的介绍-创建应用、配置应用、上线应用

【资源下载:App支付DEMO&SDK、生成与配置密钥】

必发365游戏官方网址 5

资源下载汇总

必发365游戏官方网址 6

签名工具

注意签名工具目录不能包含中文

必发365游戏官方网址 7

签名工具的使用

必发365游戏官方网址 8

上传密钥

这里上传的是rsa_public_key.pemJava版签名使用的密钥是rsa_private_key_pkcs8.pem

3、支付宝App支付Android集成流程详解

官方文档点击这里

1、导入支付宝SDK
其中SDK在图资源下载汇总的WS.APP_PAY_SDK_BASE_20.zip中

2、修改Manifest

在商户应用工程的AndroidManifest.xml文件里面添加声明:

android:name=”com.alipay.sdk.app.H5PayActivity”

android:configChanges=”orientation|keyboardHidden|navigation”

android:exported=”false”

android:screenOrientation=”behind” >

android:name=”com.alipay.sdk.auth.AuthActivity”

android:configChanges=”orientation|keyboardHidden|navigation”

android:exported=”false”

android:screenOrientation=”behind” >

3、权限声明

4、如需混洗、添加混淆规则

在商户应用工程的proguard-project.txt里添加以下相关规则:

alipaySDK-xxxxx.jar根据下载的做响应的修改

-libraryjars libs/alipaySDK-xxxxx.jar

-keep class com.alipay.android.app.IAlixPay{*;}

-keep class com.alipay.android.app.IAlixPay$Stub{*;}

-keep class com.alipay.android.app.IRemoteServiceCallback{*;}

-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}

-keep class com.alipay.sdk.app.PayTask{ public *;}

-keep class com.alipay.sdk.app.AuthTask{ public *;}

5、支付接口调用

获取PayTask支付对象调用支付(支付行为需要在独立的非ui线程中执行

)具体实现参考客户端实现,调用支付需要使用到orderInfo具体实现参考服务端实现。

6、支付结果获取和处理

调用pay方法支付后,将通过2种途径获得支付结果:

1、同步返回商户应用客户端通过当前调用支付的Activity的Handler对象,通过它的回调函数获取支付结果。

2、异步通知商户需要提供一个http协议的接口,包含在请求支付的入参中,其key对应notify_url。支付宝服务器在支付完成后,会以POST方式调用notify_url传输数据。

4、服务端实现

代码来自Demo 并做简单的封装

必发365游戏官方网址 9

具体实现截图

设置支付宝业务参数

必发365游戏官方网址 10

设置支付宝业务参数

注意:支付宝App支付不支持沙盒模式(此坑纠结了很长时间),使用沙盒模式会出现ALI40247错误,文末有错误的详细说明。

核心实现代码如下

/**

* App支付

*/

public void appPay(){

String orderInfo;

try {

String body=”我是测试数据”;

String passback_params=”123″;

String subject=”1″;

String total_amount=”0.01″;

String notify_url=””;

String appId;

String rsa_private;

if (isDebug) {

appId=prop.get(“test_appId”).trim();

rsa_private=prop.get(“test_rsa_private”).trim();

System.out.println(“test。。。。”);

}else {

appId=prop.get(“appId”).trim();

rsa_private=prop.get(“rsa_private”).trim();

}

System.out.println(“appId:”+appId);

System.out.println(“rsa_private:”+rsa_private);

BizContent content = new BizContent();

content.setBody(body);

content.setOut_trade_no(OrderInfoUtil2_0.getOutTradeNo());;

content.setPassback_params(passback_params);

content.setSubject(subject);

content.setTotal_amount(total_amount);

content.setProduct_code(“QUICK_MSECURITY_PAY”);

Map params =
OrderInfoUtil2_0.buildOrderParamMap(appId,notify_url,content);

String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

String sign = OrderInfoUtil2_0.getSign(params, rsa_private);

orderInfo = orderParam + “&” + sign;

log.info(“orderInfo>”+orderInfo);

result.success(orderInfo);

renderJson(result);

} catch (Exception e) {

e.printStackTrace();

result.addError(“system error”);

}

}

具体实现参考【开源项目】

补充 使用支付服务端SDK实现获取预付订单

1、先获取到AlipayClient

alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey,
format, charset, alipayPulicKey, signType);

2、使用AlipayTradeAppPayRequest封装请求

/**

* App支付

* @param model

* @param notifyUrl

* @return

* @throws AlipayApiException

*/

public static String startAppPayStr(AlipayTradeAppPayModel model, String
notifyUrl) throws AlipayApiException{

AlipayTradeAppPayResponse response = appPay(model,notifyUrl);

return response.getBody();

}

/**

* App 支付

*

* @param model

* @param notifyUrl

* @return

* @throws AlipayApiException

*/

public static AlipayTradeAppPayResponse appPay(AlipayTradeAppPayModel
model, String notifyUrl) throws AlipayApiException{

//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。

request.setBizModel(model);

request.setNotifyUrl(notifyUrl);

//这里和普通的接口调用不同,使用的是sdkExecute

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

return response;

}

3、控制器封装数据给客户端

/**

* app支付

*/

public void appPay(){

try {

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

model.setBody(“我是测试数据”);

model.setSubject(“App支付测试-By Javen”);

model.setOutTradeNo(StringUtils.getOutTradeNo());

model.setTimeoutExpress(“30m”);

model.setTotalAmount(“0.01”);

model.setPassbackParams(“callback params”);

model.setProductCode(“QUICK_MSECURITY_PAY”);

String orderInfo =
AliPayApi.startAppPayStr(model,AliPayApi.notify_domain+”/alipay/app_pay_notify”);

result.success(orderInfo);

renderJson(result);

} catch (AlipayApiException e) {

e.printStackTrace();

result.addError(“system error”);

}

}

服务端异步通知

/**

* App支付支付回调通知

*

* docType=1#s3

*/

public void app_pay_notify() {

try {

// 获取支付宝POST过来反馈信息

Map params = AliPayApi.toMap(getRequest());

for (Map.Entry entry : params.entrySet()) {

System.out.println(entry.getKey() + ” = ” + entry.getValue());

}

//
切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。

// boolean AlipaySignature.rsaCheckV1(Map params,

// String publicKey, String charset, String sign_type)

boolean flag = AlipaySignature.rsaCheckV1(params,
AliPayApi.ALIPAY_PUBLIC_KEY, AliPayApi.CHARSET,

AliPayApi.SIGN_TYPE);

if (flag) {

// TODO

System.out.println(“success”);

renderText(“success”);

return;

} else {

// TODO

System.out.println(“failure”);

renderText(“failure”);

}

} catch (AlipayApiException e) {

e.printStackTrace();

renderText(“failure”);

}

}

将异步通知的参数转化为Map

/**

* 将异步通知的参数转化为Map

* @param request

* @return

*/

public static Map toMap(HttpServletRequest request) {

System.out.println(“>>>>” + request.getQueryString());

Map params = new HashMap();

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] + “,”;

}

// 乱码解决,这段代码在出现乱码时使用。

// valueStr = new String(valueStr.getBytes(“ISO-8859-1”), “utf-8”);

params.put(name, valueStr);

}

return params;

}

5、客户端实现

客户端请求此action返回orderInfo,默认的访问地址为

成功将返回:

{

“code”: 0,

“data”:
“charset=utf-8&biz_content=%7B%22out_trade_no%22%3A%22120822453414812%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22passback_params%22%3A%22123%22%7D&method=alipay.trade.app.pay&format=json¬ify_url=http%3A%2F%2Fjaven.ittun.com%2Falipay%2Fpay_notify&app_id=2016102000727659&sign_type=RSA&version=1.0×tamp=2016-12-08+22%3A45%3A34&sign=m6fpNI58jkOIHROtm8Q2V1Ei7bxXc14JHtJEeqGM0B8dWlq3d%2FfAqpoQTZgeBb%2FVK%2B%2BydOJzVvSWc89dBxhYUq72KOeUwHiKlRJBFMnEMAZbJlRxqu9%2BRX2q7HSRmA6WRg75O68HZhkIhtO3bSNx3s710tMHmQCN230JoVWiwHw%3D”,

“message”: null

}

/**

* 获取支付宝App支付订单信息

*必发365游戏官方网址, @return

*/

public String getAliPayOrderInfo(Order order){

String result=HttpKit.get(Constants.ALIPAY_URL);

return result;

}

异步获取orderInfo

public class AliPay extends AsyncTask {

private Activity mContext;

public AliPay(Activity context) {

this.mContext = context;

}

@Override

protected String doInBackground(Object… params) {

return 
IPayLogic.getIntance(mContext).getAliPayOrderInfo((Order)params[0]);

}

@Override

protected void onPostExecute(String result) {

try {

if (result!=null) {

System.out.println(“AliPay result>”+result);

JSONObject data = new JSONObject(result);

String message = data.getString(“message”);

int code = data.getInt(“code”);

if(code == 0){

String orderInfo = data.getString(“data”);

Toast.makeText(mContext, “正在调起支付”, Toast.LENGTH_SHORT).show();

IPayLogic.getIntance(mContext).startAliPay(orderInfo);

}else{

Log.d(“PAY_GET”, “返回错误”+message);

//                    Toast.makeText(mContext, “返回错误:”+message,
Toast.LENGTH_SHORT).show();

}

}else {

System.out.println(“get  AliPay exception, is null”);

}

} catch (Exception e) {

Log.e(“PAY_GET”, “异常:”+e.getMessage());

Toast.makeText(mContext, “异常:”+e.getMessage(),
Toast.LENGTH_SHORT).show();

}

super.onPostExecute(result);

}

}

支付接口调用

public void startAliPay(final String orderInfo){

Runnable payRunnable = new Runnable() {

@Override

public void run() {

PayTask alipay = new PayTask(mContext);

Map result = alipay.payV2(orderInfo, true);

Message msg = new Message();

msg.obj = result;

mHandler.sendMessage(msg);

}

};

Thread payThread = new Thread(payRunnable);

payThread.start();

}

客户端通过回调函数获取支付结果

private Handler mHandler = new Handler(Looper.getMainLooper()) {

@SuppressWarnings(“unchecked”)

public void handleMessage(Message msg) {

PayResult payResult = new PayResult((Map) msg.obj);

System.out.println(“alipay call “+payResult.toString());

String resultStatus = payResult.getResultStatus();

String memo = payResult.getMemo();

if (Constants.payListener !=null){

//返回状态以及详细的描述参考

//

Constants.payListener.onPay(-2,resultStatus,memo);

}

}

};

客户端具体使用方法

public void testAliPay(View view){

Toast.makeText(this, “支付宝测试”, Toast.LENGTH_SHORT).show();

Order order = new Order();

order.setBody(“会员充值中心”);

order.setParaTradeNo(System.currentTimeMillis()+””);

order.setTotalFee(20);

order.setAttach(“json”);//附加参数

order.setNofityUrl(“

IPay.getIntance(MainActivity.this).toPay(IPay.PayMode.ALIPAY,order,new
IPay.IPayListener() {

@Override

public void onPay(int wxcode, String alicode, String message) {

System.out.println(“回调过来的状态》”+alicode+”
message>”+((message!=null && message.isEmpty())?””:message));

Toast.makeText(MainActivity.this, “回调过来的状态》” + alicode,
Toast.LENGTH_SHORT).show();

}

});

}

6、常见错误解决方案

APP支付报错ALI40247处理方案

ALI40247的错误

有2种情况 1、没有权限 2、签名失败

可以查看论坛提供的这个解决方案

AL38173的错误一般是参数问题造成的,建议检查请求参数,对照文档查看,比如:参数少了、多了、乱码、名称不对,还有必传参数是否都请求提交给支付宝了等等.

如果在网上查阅质料还未解决,可以寻求阿里的在线支持【支持中心】

此项目已开源 赶快来围观 Start支持下吧

【客户端开源地址-JPay】【服务端端开源地址-在com.javen.alipay包名下】

作者:Javen205

链接:

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website