├── README.md ├── package.json ├── plugin.xml ├── src └── android │ ├── alipay │ ├── AlipayPlugin.java │ ├── PayKeys.java │ └── PayRun.java │ ├── bean │ └── PayResult.java │ ├── libs │ └── alipaysdk.jar │ └── util │ ├── Base64.java │ └── SignUtils.java └── www └── alipay.js /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## cordova集成支付宝插件 3 | 4 | ### 前言 5 | 6 | 插件编写于15年11月份,如果之后支付宝更换了支付方式,本插件会失效,在此之前可以正常使用 7 | 8 | #### 说明 9 | * SDK 10 | 11 | 需要和支付宝签约`移动支付`,然后下载[SDK](http://download.alipay.com/public/api/base/WS_MOBILE_PAY_SDK_BASE.zip),里面有Android、IOS提供了完整的文档,看需求选择业务需要的。 12 | 13 | * 支持平台 14 | 15 | Android 16 | 17 | #### 使用 18 | 19 | 在添加插件之前,需要配置与支付宝签约的帐号密匙 20 | 21 | **yourProject\plugins\alipay\src\android\alipay\PayKeys.java** 22 | 23 | package com.yumemor.cordova.alipay; 24 | 25 | /** 26 | * 商户配置信息 27 | * 28 | * @author yy 29 | * 30 | */ 31 | public final class PayKeys { 32 | 33 | // 合作身份者id,以2088开头的16位纯数字 34 | public static final String DEFAULT_PARTNER = ""; 35 | 36 | // 收款支付宝账号 37 | public static final String DEFAULT_SELLER = ""; 38 | 39 | // 商户私钥 自助生成 40 | public static final String PRIVATE = ""; 41 | 42 | // 支付宝默认公钥 请勿修改 43 | public static final String PUBLIC = ""; 44 | 45 | } 46 | 47 | **添加插件到你的项目** 48 | 49 | cordova plugins add cordova-plugin-alipay-pay 50 | 51 | **js调用** 52 | 53 | window.plugins.Alipay.pay(out_trade_no,subject,body,total_fee,successCallback,errorCallback,callbackUrl); 54 | 55 | **参数说明:** 56 | 57 | * out_trade_no: 订单号(不能重复) 58 | * subject: 商品名称 59 | * body: 描述 60 | * total_fee: 价格 61 | * successCallback: 成功回调 62 | * errorCallback: 失败回调 63 | * callbackUrl: 回调地址/支付宝调用 64 | 65 | 当调用方法后如果安装了支付宝会调用支付宝进行支付,如果没有则用HTML5支付。 66 | 67 | #### 截图 68 | 69 | **支付宝:** 70 | 71 | ![image](http://7xnxsw.com1.z0.glb.clouddn.com/cordova-alipay-plugin/Screenshot_2015-11-02-14-08-50.png) 72 | 73 | **HTML5:** 74 | 75 | ![image](http://7xnxsw.com1.z0.glb.clouddn.com/cordova-alipay-plugin/Screenshot_2015-11-02-14-09-23.png) 76 | 77 | **回调:** 78 | 79 | ![image](http://7xnxsw.com1.z0.glb.clouddn.com/cordova-alipay-plugin/Screenshot_2015-11-02-14-09-03.png) 80 | 81 | * 注意 82 | 83 | 如果配置错了密匙,是不会打开支付界面的。 84 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-alipay-pay", 3 | "version": "1.0.3", 4 | "cordova_name": "Alipay", 5 | "description": "Cordova Alipay Plugin", 6 | "license": "MIT", 7 | "author": "yumemor", 8 | "cordova": { 9 | "platforms": [ 10 | "android" 11 | ] 12 | }, 13 | "keywords": [ 14 | "pay", 15 | "alipay", 16 | "cordova", 17 | "ecosystem:cordova", 18 | "cordova-android" 19 | ], 20 | "engines": [ 21 | { 22 | "name": "cordova", 23 | "version": ">=3.0.0" 24 | } 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/yumemor/cordova-plugin-alipay.git" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/yumemor/cordova-plugin-alipay/issues" 32 | }, 33 | "homepage": "https://github.com/yumemor/cordova-plugin-alipay.git#readme", 34 | "main": "index.js", 35 | "scripts": { 36 | "test": "echo \"Error: no test specified\" && exit 1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | Alipay 7 | Cordova Alipay Plugin 8 | Apache 2.0 9 | cordova,alipay 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 35 | 36 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/android/alipay/AlipayPlugin.java: -------------------------------------------------------------------------------- 1 | package com.yumemor.cordova.alipay; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | import java.net.URLEncoder; 6 | 7 | import org.apache.cordova.CallbackContext; 8 | import org.apache.cordova.CordovaPlugin; 9 | 10 | import org.json.JSONArray; 11 | import org.json.JSONObject; 12 | 13 | import com.yumemor.cordova.util.SignUtils; 14 | 15 | /** 16 | * 17 | * 基于Cordova实现的支付宝插件 18 | * 19 | * @author yy 20 | * 21 | */ 22 | public class AlipayPlugin extends CordovaPlugin { 23 | 24 | public boolean execute(String action , JSONArray args , CallbackContext callbackContext) { 25 | 26 | if (action.equals("pay")) { // 支付动作 27 | 28 | try { 29 | 30 | if(args.isNull(0)){ 31 | 32 | callbackContext.error("无效的参数"); 33 | 34 | return false; 35 | 36 | }else{ 37 | 38 | JSONObject json = args.optJSONObject(0); 39 | 40 | String out_trade_no = json.optString("out_trade_no"); //订单号 41 | 42 | String subject = json.optString("subject"); //商品名称 43 | 44 | String body = json.optString("body"); //商品内容 45 | 46 | String total_fee = json.optString("total_fee"); //金额 47 | 48 | String url = json.optString("callbackUrl"); //回调地址 49 | 50 | String orderInfo = getOrderInfo(out_trade_no , subject,body , total_fee , url); 51 | 52 | String sign = sign(orderInfo); //签名 53 | 54 | try { 55 | 56 | sign = URLEncoder.encode(sign, "UTF-8"); //URL编码 57 | 58 | } catch (UnsupportedEncodingException e) { 59 | 60 | callbackContext.error("签名错误!"); 61 | 62 | return false; 63 | } 64 | 65 | String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType(); 66 | 67 | PayRun payRun = new PayRun(cordova.getActivity(),payInfo,callbackContext); 68 | 69 | Thread payThread = new Thread(payRun); 70 | 71 | payThread.start(); //启动线程进行支付 72 | 73 | } 74 | 75 | return true; 76 | 77 | } catch (Exception ex) { 78 | 79 | callbackContext.error("支付失败!"); 80 | 81 | return false; 82 | } 83 | 84 | } else { 85 | 86 | callbackContext.error("无效的Action"); 87 | 88 | return false; 89 | } 90 | 91 | } 92 | 93 | /** 94 | * create the order info. 创建订单信息 95 | * 96 | */ 97 | public String getOrderInfo(String out_trade_no, String subject,String body, String price, String url) { 98 | 99 | StringBuffer sb = new StringBuffer(); 100 | 101 | // 合作者身份ID 102 | sb.append("partner=" + "\"" + PayKeys.DEFAULT_PARTNER + "\""); 103 | 104 | // 卖家支付宝账号 105 | sb.append("&seller_id=" + "\"" + PayKeys.DEFAULT_SELLER + "\""); 106 | 107 | // 商户网站唯一订单号 108 | sb.append("&out_trade_no=" + "\"" + out_trade_no + "\""); 109 | 110 | // 商品名称 111 | sb.append("&subject=" + "\"" + subject + "\""); 112 | 113 | // 商品详情 114 | sb.append("&body=" + "\"" + body + "\""); 115 | 116 | // 商品金额 117 | sb.append("&total_fee=" + "\"" + price + "\""); 118 | 119 | // 服务器异步通知页面路径 //服务器异步通知页面路径 参数 notify_url,如果商户没设定,则不会进行该操作 120 | sb.append("¬ify_url=" + "\"" + url + "\""); 121 | 122 | // 接口名称, 固定值 123 | sb.append("&service=\"mobile.securitypay.pay\""); 124 | 125 | // 支付类型, 固定值 126 | sb.append("&payment_type=\"1\""); 127 | 128 | // 参数编码, 固定值 129 | sb.append("&_input_charset=\"utf-8\""); 130 | 131 | // 设置未付款交易的超时时间 132 | // 默认30分钟,一旦超时,该笔交易就会自动被关闭。 133 | // 取值范围:1m~15d。 134 | // m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。 135 | // 该参数数值不接受小数点,如1.5h,可转换为90m。 136 | sb.append("&it_b_pay=\"30m\""); 137 | 138 | // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空 139 | sb.append("&return_url=\"m.alipay.com\""); 140 | 141 | // 调用银行卡支付,需配置此参数,参与签名, 固定值 142 | // orderInfo += "&paymethod=\"expressGateway\""; 143 | 144 | return sb.toString(); 145 | 146 | } 147 | 148 | /** 149 | * sign the order info. 对订单信息进行签名 150 | * 151 | * @param content 152 | * 待签名订单信息 153 | */ 154 | public String sign(String content) { 155 | return SignUtils.sign(content, PayKeys.PRIVATE); 156 | } 157 | 158 | /** 159 | * get the sign type we use. 获取签名方式 160 | * 161 | */ 162 | public String getSignType() { 163 | return "sign_type=\"RSA\""; 164 | } 165 | 166 | } -------------------------------------------------------------------------------- /src/android/alipay/PayKeys.java: -------------------------------------------------------------------------------- 1 | package com.yumemor.cordova.alipay; 2 | 3 | /** 4 | * 商户配置信息 5 | * 6 | * @author yy 7 | * 8 | */ 9 | public final class PayKeys { 10 | 11 | // 合作身份者id,以2088开头的16位纯数字 12 | public static final String DEFAULT_PARTNER = ""; 13 | 14 | // 收款支付宝账号 15 | public static final String DEFAULT_SELLER = ""; 16 | 17 | // 商户私钥 自助生成 18 | public static final String PRIVATE = ""; 19 | 20 | // 支付宝默认公钥 请勿修改 21 | public static final String PUBLIC = ""; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/android/alipay/PayRun.java: -------------------------------------------------------------------------------- 1 | package com.yumemor.cordova.alipay; 2 | 3 | import org.apache.cordova.CallbackContext; 4 | import org.json.JSONObject; 5 | 6 | import android.app.Activity; 7 | 8 | import com.alipay.sdk.app.PayTask; 9 | import com.yumemor.cordova.bean.PayResult; 10 | 11 | /** 12 | * 支付线程 13 | * 14 | * @author yy 15 | * 16 | */ 17 | public class PayRun implements Runnable { 18 | 19 | /** 20 | * cordova.getActivity() 21 | */ 22 | private Activity cordovaActivity; 23 | 24 | /** 25 | * cordova的回调 26 | */ 27 | private CallbackContext callbackContext; 28 | 29 | /** 30 | * 支付信息 31 | */ 32 | private String payInfo; 33 | 34 | public PayRun(Activity cordovaActivity , String payInfo , CallbackContext callbackContext) { 35 | 36 | this.callbackContext = callbackContext; 37 | 38 | this.cordovaActivity = cordovaActivity; 39 | 40 | this.payInfo = payInfo; 41 | } 42 | 43 | @Override 44 | public void run() { 45 | 46 | PayTask alipay = new PayTask(cordovaActivity); 47 | 48 | String result = alipay.pay(payInfo); //支付 49 | 50 | callbackContext.success(new PayResult(result).toString()); //返回支付结果 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/android/bean/PayResult.java: -------------------------------------------------------------------------------- 1 | package com.yumemor.cordova.bean; 2 | 3 | /** 4 | * 支付结果 5 | * 6 | * @author yy 7 | * 8 | */ 9 | public class PayResult { 10 | 11 | /** 12 | * 返回状态 13 | */ 14 | private String resultStatus; 15 | 16 | /** 17 | * 结果 18 | */ 19 | private String result; 20 | 21 | /** 22 | * 备忘录 23 | */ 24 | private String memo; 25 | 26 | public PayResult(String rawResult) { 27 | 28 | String[] resultParams = rawResult.split(";"); 29 | 30 | for (String resultParam : resultParams) { 31 | 32 | if (resultParam.startsWith("resultStatus")) { 33 | 34 | resultStatus = gatValue(resultParam, "resultStatus"); 35 | 36 | continue; 37 | 38 | } 39 | 40 | if (resultParam.startsWith("result")) { 41 | 42 | result = gatValue(resultParam, "result"); 43 | 44 | continue; 45 | 46 | } 47 | 48 | if (resultParam.startsWith("memo")) { 49 | 50 | memo = gatValue(resultParam, "memo"); 51 | 52 | continue; 53 | 54 | } 55 | } 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | 61 | return String.format("{'resultStatus':%s,'result':%s,'memo':%s}",resultStatus , result , memo); 62 | 63 | } 64 | 65 | private String gatValue(String content, String key) { 66 | 67 | String prefix = key + "={"; 68 | 69 | return content.substring(content.indexOf(prefix) + prefix.length() , content.lastIndexOf("}")); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/android/libs/alipaysdk.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yumexupanic/cordova-plugin-alipay/0dafceb3bc3a8cc3ba67ea65466132d07981d920/src/android/libs/alipaysdk.jar -------------------------------------------------------------------------------- /src/android/util/Base64.java: -------------------------------------------------------------------------------- 1 | package com.yumemor.cordova.util; 2 | 3 | public final class Base64 { 4 | 5 | private static final int BASELENGTH = 128; 6 | private static final int LOOKUPLENGTH = 64; 7 | private static final int TWENTYFOURBITGROUP = 24; 8 | private static final int EIGHTBIT = 8; 9 | private static final int SIXTEENBIT = 16; 10 | private static final int FOURBYTE = 4; 11 | private static final int SIGN = -128; 12 | private static char PAD = '='; 13 | private static byte[] base64Alphabet = new byte[BASELENGTH]; 14 | private static char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; 15 | 16 | static { 17 | for (int i = 0; i < BASELENGTH; ++i) { 18 | base64Alphabet[i] = -1; 19 | } 20 | for (int i = 'Z'; i >= 'A'; i--) { 21 | base64Alphabet[i] = (byte) (i - 'A'); 22 | } 23 | for (int i = 'z'; i >= 'a'; i--) { 24 | base64Alphabet[i] = (byte) (i - 'a' + 26); 25 | } 26 | 27 | for (int i = '9'; i >= '0'; i--) { 28 | base64Alphabet[i] = (byte) (i - '0' + 52); 29 | } 30 | 31 | base64Alphabet['+'] = 62; 32 | base64Alphabet['/'] = 63; 33 | 34 | for (int i = 0; i <= 25; i++) { 35 | lookUpBase64Alphabet[i] = (char) ('A' + i); 36 | } 37 | 38 | for (int i = 26, j = 0; i <= 51; i++, j++) { 39 | lookUpBase64Alphabet[i] = (char) ('a' + j); 40 | } 41 | 42 | for (int i = 52, j = 0; i <= 61; i++, j++) { 43 | lookUpBase64Alphabet[i] = (char) ('0' + j); 44 | } 45 | lookUpBase64Alphabet[62] = (char) '+'; 46 | lookUpBase64Alphabet[63] = (char) '/'; 47 | 48 | } 49 | 50 | private static boolean isWhiteSpace(char octect) { 51 | return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); 52 | } 53 | 54 | private static boolean isPad(char octect) { 55 | return (octect == PAD); 56 | } 57 | 58 | private static boolean isData(char octect) { 59 | return (octect < BASELENGTH && base64Alphabet[octect] != -1); 60 | } 61 | 62 | /** 63 | * Encodes hex octects into Base64 64 | * 65 | * @param binaryData 66 | * Array containing binaryData 67 | * @return Encoded Base64 array 68 | */ 69 | public static String encode(byte[] binaryData) { 70 | 71 | if (binaryData == null) { 72 | return null; 73 | } 74 | 75 | int lengthDataBits = binaryData.length * EIGHTBIT; 76 | if (lengthDataBits == 0) { 77 | return ""; 78 | } 79 | 80 | int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; 81 | int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; 82 | int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 83 | : numberTriplets; 84 | char encodedData[] = null; 85 | 86 | encodedData = new char[numberQuartet * 4]; 87 | 88 | byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; 89 | 90 | int encodedIndex = 0; 91 | int dataIndex = 0; 92 | 93 | for (int i = 0; i < numberTriplets; i++) { 94 | b1 = binaryData[dataIndex++]; 95 | b2 = binaryData[dataIndex++]; 96 | b3 = binaryData[dataIndex++]; 97 | 98 | l = (byte) (b2 & 0x0f); 99 | k = (byte) (b1 & 0x03); 100 | 101 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) 102 | : (byte) ((b1) >> 2 ^ 0xc0); 103 | byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) 104 | : (byte) ((b2) >> 4 ^ 0xf0); 105 | byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) 106 | : (byte) ((b3) >> 6 ^ 0xfc); 107 | 108 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; 109 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; 110 | encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; 111 | encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; 112 | } 113 | 114 | // form integral number of 6-bit groups 115 | if (fewerThan24bits == EIGHTBIT) { 116 | b1 = binaryData[dataIndex]; 117 | k = (byte) (b1 & 0x03); 118 | 119 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) 120 | : (byte) ((b1) >> 2 ^ 0xc0); 121 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; 122 | encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; 123 | encodedData[encodedIndex++] = PAD; 124 | encodedData[encodedIndex++] = PAD; 125 | } else if (fewerThan24bits == SIXTEENBIT) { 126 | b1 = binaryData[dataIndex]; 127 | b2 = binaryData[dataIndex + 1]; 128 | l = (byte) (b2 & 0x0f); 129 | k = (byte) (b1 & 0x03); 130 | 131 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) 132 | : (byte) ((b1) >> 2 ^ 0xc0); 133 | byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) 134 | : (byte) ((b2) >> 4 ^ 0xf0); 135 | 136 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; 137 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; 138 | encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; 139 | encodedData[encodedIndex++] = PAD; 140 | } 141 | 142 | return new String(encodedData); 143 | } 144 | 145 | /** 146 | * Decodes Base64 data into octects 147 | * 148 | * @param encoded 149 | * string containing Base64 data 150 | * @return Array containind decoded data. 151 | */ 152 | public static byte[] decode(String encoded) { 153 | 154 | if (encoded == null) { 155 | return null; 156 | } 157 | 158 | char[] base64Data = encoded.toCharArray(); 159 | // remove white spaces 160 | int len = removeWhiteSpace(base64Data); 161 | 162 | if (len % FOURBYTE != 0) { 163 | return null;// should be divisible by four 164 | } 165 | 166 | int numberQuadruple = (len / FOURBYTE); 167 | 168 | if (numberQuadruple == 0) { 169 | return new byte[0]; 170 | } 171 | 172 | byte decodedData[] = null; 173 | byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; 174 | char d1 = 0, d2 = 0, d3 = 0, d4 = 0; 175 | 176 | int i = 0; 177 | int encodedIndex = 0; 178 | int dataIndex = 0; 179 | decodedData = new byte[(numberQuadruple) * 3]; 180 | 181 | for (; i < numberQuadruple - 1; i++) { 182 | 183 | if (!isData((d1 = base64Data[dataIndex++])) 184 | || !isData((d2 = base64Data[dataIndex++])) 185 | || !isData((d3 = base64Data[dataIndex++])) 186 | || !isData((d4 = base64Data[dataIndex++]))) { 187 | return null; 188 | }// if found "no data" just return null 189 | 190 | b1 = base64Alphabet[d1]; 191 | b2 = base64Alphabet[d2]; 192 | b3 = base64Alphabet[d3]; 193 | b4 = base64Alphabet[d4]; 194 | 195 | decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); 196 | decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 197 | decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); 198 | } 199 | 200 | if (!isData((d1 = base64Data[dataIndex++])) 201 | || !isData((d2 = base64Data[dataIndex++]))) { 202 | return null;// if found "no data" just return null 203 | } 204 | 205 | b1 = base64Alphabet[d1]; 206 | b2 = base64Alphabet[d2]; 207 | 208 | d3 = base64Data[dataIndex++]; 209 | d4 = base64Data[dataIndex++]; 210 | if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters 211 | if (isPad(d3) && isPad(d4)) { 212 | if ((b2 & 0xf) != 0)// last 4 bits should be zero 213 | { 214 | return null; 215 | } 216 | byte[] tmp = new byte[i * 3 + 1]; 217 | System.arraycopy(decodedData, 0, tmp, 0, i * 3); 218 | tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); 219 | return tmp; 220 | } else if (!isPad(d3) && isPad(d4)) { 221 | b3 = base64Alphabet[d3]; 222 | if ((b3 & 0x3) != 0)// last 2 bits should be zero 223 | { 224 | return null; 225 | } 226 | byte[] tmp = new byte[i * 3 + 2]; 227 | System.arraycopy(decodedData, 0, tmp, 0, i * 3); 228 | tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); 229 | tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 230 | return tmp; 231 | } else { 232 | return null; 233 | } 234 | } else { // No PAD e.g 3cQl 235 | b3 = base64Alphabet[d3]; 236 | b4 = base64Alphabet[d4]; 237 | decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); 238 | decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 239 | decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); 240 | 241 | } 242 | 243 | return decodedData; 244 | } 245 | 246 | /** 247 | * remove WhiteSpace from MIME containing encoded Base64 data. 248 | * 249 | * @param data 250 | * the byte array of base64 data (with WS) 251 | * @return the new length 252 | */ 253 | private static int removeWhiteSpace(char[] data) { 254 | if (data == null) { 255 | return 0; 256 | } 257 | 258 | // count characters that's not whitespace 259 | int newSize = 0; 260 | int len = data.length; 261 | for (int i = 0; i < len; i++) { 262 | if (!isWhiteSpace(data[i])) { 263 | data[newSize++] = data[i]; 264 | } 265 | } 266 | return newSize; 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /src/android/util/SignUtils.java: -------------------------------------------------------------------------------- 1 | package com.yumemor.cordova.util; 2 | 3 | import java.security.KeyFactory; 4 | import java.security.PrivateKey; 5 | import java.security.spec.PKCS8EncodedKeySpec; 6 | 7 | 8 | public class SignUtils { 9 | 10 | private static final String ALGORITHM = "RSA"; 11 | 12 | private static final String SIGN_ALGORITHMS = "SHA1WithRSA"; 13 | 14 | private static final String DEFAULT_CHARSET = "UTF-8"; 15 | 16 | public static String sign(String content, String privateKey) { 17 | try { 18 | PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec( 19 | Base64.decode(privateKey)); 20 | KeyFactory keyf = KeyFactory.getInstance(ALGORITHM); 21 | PrivateKey priKey = keyf.generatePrivate(priPKCS8); 22 | 23 | java.security.Signature signature = java.security.Signature 24 | .getInstance(SIGN_ALGORITHMS); 25 | 26 | signature.initSign(priKey); 27 | signature.update(content.getBytes(DEFAULT_CHARSET)); 28 | 29 | byte[] signed = signature.sign(); 30 | 31 | return Base64.encode(signed); 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | 36 | return null; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /www/alipay.js: -------------------------------------------------------------------------------- 1 |  2 | cordova.define("cordova/plugins/Alipay",function(require, exports, module) { 3 | 4 | var exec = require("cordova/exec"); 5 | 6 | var Alipay = function() {}; 7 | 8 | Alipay.prototype.pay = function(out_trade_no,subject,body,total_fee,successCallback, errorCallback, callbackUrl) { 9 | 10 | if (errorCallback == null) { errorCallback = function() {}} 11 | 12 | if (typeof errorCallback != "function" || typeof successCallback != "function" || !callbackUrl) { 13 | 14 | errorCallback('参数错误!'); 15 | 16 | return; 17 | 18 | } 19 | 20 | exec(successCallback, errorCallback, 'Alipay', 'pay', [{"out_trade_no":out_trade_no, "subject": subject,"body":body, "total_fee": total_fee, "callbackUrl": callbackUrl}]); 21 | 22 | }; 23 | 24 | module.exports = new Alipay(); 25 | 26 | }); 27 | 28 | 29 | if(!window.plugins) window.plugins = {}; 30 | 31 | if (!window.plugins.Alipay) window.plugins.Alipay = cordova.require("cordova/plugins/Alipay"); 32 | 33 | --------------------------------------------------------------------------------