基本步骤及遇到的问题:
生成公钥私钥
解压:
点击进入 然后再双击:
然后会生成:
pkcs8: 私钥
public_key:公钥
关于 付款成功后,回调地址 可以给个接口的地址
1.没有APP支付权限导致
检查您使用的这个appid是否签约过APP支付这个接口的权限。
2.有移动支付接口(接口名称:mobile.securitypay.pay)权限没有app支付接口(接口名称:alipay.trade.app.pay)权限。以为可以使用APP支付接口,这是两个接口如果有移动支付接口(接口名称:mobile.securitypay.pay)权限想使 用APP支付接口(接口名称:alipay.trade.app.pay),可以进行重新签约参考《接口签约方案》第三步 帖子地址:https://openclub.alipay.com/read.php?tid=276&fid=25
3.如果已经签约了APP支付接口,还是报这个错误
需要检查商户公钥上传的位置是否正确
a.移动支付接口(接口名称:mobile.securitypay.pay)的上传合作伙伴密钥管理
b.app支付接口(接口名称:alipay.trade.app.pay)的上传开放平台密钥管理
注意:使用的接口不同上传位置不同
这个接口应该使用开放平台密钥管理里面的密钥,检查您这个接口使用的appid下面的公钥(自己上传的商户公钥)和支付宝报公钥。因为没有上传商户公钥或者使用的商户公钥和商户私钥不匹配也会导致这个错误
4.请求支付编码问题和没有做url encode
编码:就是请求了utf-8 但是用了gbk的编码
encode:app支付接口(接口名称:alipay.trade.app.pay)对请求字符串的所有一级value(biz_content作为一个value)进行encode。
5.管理中心》我的应用》状态》(注意:)已上线才可以使用否则也会报这个错误
申请上线需要填写 申请资料
6.检查应用是否已经上线
关于给服务器传参,让服务器返回 拉起支付宝的字符串:
我把签名删除了一些 下面是返回的字符串 是当做 orderInfo 用来拉起支付的:
app_id=2017021405666842&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%22%E6%89%BE%E6%B4%BB%E7%BD%91%E7%A7%AF%E5%88%86%E5%85%85%E5%80%BC%22%2C%22body%22%3A%22%E6%89%BE%E6%B4%BB%E7%BD%91%E7%A7%AF%E5%88%86%E5%85%85%E5%80%BC%22%2C%22out_trade_no%22%3A%22021811340336879%22%7D&charset=UTF-8&format=JSON&method=alipay.trade.app.pay¬ify_url=http%3A%2F%2Fzhaohuo.chuangkeweilai.cn%2Finclude%2Fpayment%2Falipayapp%2Fnotify_url.php&sign_type=RSA×tamp=2017-02-18+11%3A34%3A03&version=1.0&sign=ADus0ZXHq600d3RFWWE8tiUNm%2Fisr%2FxZtWDit%2FL%2FVNOygTRLaJKlyfEWgN9v%2Bf9v5TkixWE5L9UPK6wM36E0MQOMJM8kG8i8xC6B4ss6ujExFZaGBDexLQMrOHXccxwzlNS0LKZE2uInrznlecjDwMyqHpPIyKs4kUwPmoAAQ1Hj2kxe6a99BA%3D%3D
一些固定的可在 后台固定 可以只传一些可变的参数
传参时 到后台会遇到 biz_content 中 转义 \ 的问题
php的处理:
(上面的方法)该方法返回的data --- 就是 拉起支付 所需的 orderInfo
php端 回调地址中的处理:
安卓端的处理:
case 2: // ToastUtils.showToast(mContext,"支付宝支付"); Mapparams = OrderInfoUtil2_0.buildOrderParamMap(AliPayParams.APPID, et_chongzhi.getText().toString().trim(), "余额充值", "充值", "C"+System.currentTimeMillis()+"_"+user_id); StringBuilder sb = new StringBuilder(); List keys = new ArrayList (params.keySet()); Collections.sort(keys); for (int i = 0; i < keys.size(); i++) { if (i == keys.size()-1){ sb.append(keys.get(i)+"="+params.get(keys.get(i))); }else { sb.append(keys.get(i) + "=" + params.get(keys.get(i)) + "&"); } } map.clear(); map.put("prestr",sb.toString()); LogUtils.e(mContext,"请求传的东西prestr",sb.toString()); for (Map.Entry m: params.entrySet()){ map.put(m.getKey(),m.getValue()); } requestNet_POST(NetPath.REQUEST_INFO_SIGN,ALIPAY,map); break;
----- 下面这个方法为 demo的 OrderInfoUtil2_0 里面的
public static MapbuildOrderParamMap(String app_id,String total_amount,String productSubject,String productDesc,String orderNo) { Map keyValues = new HashMap (); keyValues.put("app_id", app_id); keyValues.put("biz_content", "{\"timeout_express\":\"30m\"," + "\"product_code\":\"QUICK_MSECURITY_PAY\"," + "\"total_amount\":\""+total_amount+"\"," + "\"subject\":\""+productSubject+"\"," + "\"body\":\""+productDesc+"\"," + "\"out_trade_no\":\"" + orderNo + "\"}"); // 下面的这些参数 我们这边选择了 在后台固定 所以我都注释掉了 // keyValues.put("notify_url", "http://yanglao.wbkeji.cn/index.php/Api/Payment/alipayNotify"); // keyValues.put("charset", "utf-8"); // // keyValues.put("method", "alipay.trade.app.pay"); // keyValues.put("format", "JSON"); // // keyValues.put("sign_type", "RSA"); // "2016-07-29 16:55:53" // SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // Date date = new Date(System.currentTimeMillis()); // Log.e("Time:",simpleDateFormat.format(date)); // keyValues.put("timestamp", simpleDateFormat.format(date)); // // keyValues.put("version", "1.0"); return keyValues; }
public void onSucceedPaser(int what, Gson gson, Responseresponse) { super.onSucceedPaser(what, gson, response); // LogUtils.e(mContext,"请求成功的字符串:",response.get()); switch (what){ case ALIPAY: try { GetPrivateKeyBean alibean = gson.fromJson(response.get(),GetPrivateKeyBean.class); if (alibean!=null){ if (!TextUtils.isEmpty(alibean.getData())){ // LogUtils.e(mContext,"private key1:",alibean.getData()); payV2(alibean.getData()); } } }catch (Exception e){ LogUtils.e(mContext,"解析错误",""); } break; } }
/** * 支付宝支付业务 * * @param */ public void payV2(String ssign) { LogUtils.e(mContext,"返回的 : "+ssign,""); final String orderInfo = ssign; Runnable payRunnable = new Runnable() { @Override public void run() { PayTask alipay = new PayTask(Me_ShoppingCart_Order_Pay.this); Mapresult = alipay.payV2(orderInfo, true); Log.i("msp", result.toString()); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; mHandler.sendMessage(msg); } }; Thread payThread = new Thread(payRunnable); payThread.start(); }
private static final int SDK_PAY_FLAG = 1; private static final int ALIPAY = 1; final Mapstrmap = new HashMap (); @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @SuppressWarnings("unused") public void handleMessage(Message msg) { switch (msg.what) { case SDK_PAY_FLAG: { @SuppressWarnings("unchecked") PayResult payResult = new PayResult((Map ) msg.obj); /** 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。 */ String resultInfo = payResult.getResult();// 同步返回需要验证的信息 String resultStatus = payResult.getResultStatus(); // 判断resultStatus 为9000则代表支付成功 if (TextUtils.equals(resultStatus, "9000")) { // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。 Toast.makeText(Me_ShoppingCart_Order_Pay.this, "支付成功", Toast.LENGTH_SHORT).show(); } else { // 该笔订单真实的支付结果,需要依赖服务端的异步通知。 Toast.makeText(Me_ShoppingCart_Order_Pay.this, "支付失败", Toast.LENGTH_SHORT).show(); } break; } default: break; } }; };
关于签名:
.net php 后台的 直接使用非pkcs8 格式的私钥
java后台 使用pkcs8格式的私钥
两种格式的私钥生成的签名是相同的
关于验签:
验签时使用的是支付宝公钥 (不是应用公钥)
如果验签使用应用公钥 则会验签失败