开发环境Visual Studio 2015,Xamarin 3.11.1537,Xamarin Android5.1.7.12
下载支付宝移动支付的SDK(http://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1),找到Andriud的SDK,其中有一个alipaySDK-20151014.jar(这个版本,以后肯定会变化),这是我们使用的重点。
在Visual Studio中创建一个绑定库文件
把支付宝的alipaySDK-20151014.jar添加到Jars文件夹下,先中alipaySDK-20151014.jar,打开属性窗口,设置生成操作为EmbeddedJar,库文件搞定。
Android中使用绑定库文件
在Visual Studio中创建一个BlankApp应用,然后在打开项目属性,Android Manifest选项卡,在Required permissions中选择ACCESS_WIFI_STATE和INTERNET权限,添加绑定库生成的dll到当前项目的引用中。
添加签名生成类
using System; using System.Text; using System.IO; using System.Security.Cryptography; namespace App1 { class SignatureUtils { ////// 签名 /// /// 需要签名的内容 /// 私钥 ///public static string Sign(string content, string privateKey) { byte[] Data = Encoding.GetEncoding("utf-8").GetBytes(content); RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey); SHA1 sh = new SHA1CryptoServiceProvider(); byte[] signData = rsa.SignData(Data, sh); sh.Clear(); return Convert.ToBase64String(signData); } /// /// 对prikey进行处理,C#API默认的prikey是xml格式的,所以需要进行处理 /// /// ///private static RSACryptoServiceProvider DecodePemPrivateKey(String pemstr) { byte[] pkcs8privatekey; pkcs8privatekey = Convert.FromBase64String(pemstr); if (pkcs8privatekey != null) { RSACryptoServiceProvider rsa = DecodePrivateKeyInfo(pkcs8privatekey); return rsa; } else return null; } /// /// 转换prikey /// /// ///private static RSACryptoServiceProvider DecodePrivateKeyInfo(byte[] pkcs8) { byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; byte[] seq = new byte[15]; MemoryStream mem = new MemoryStream(pkcs8); int lenstream = (int)mem.Length; BinaryReader binr = new BinaryReader(mem); byte bt = 0; ushort twobytes = 0; try { twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) binr.ReadByte(); else if (twobytes == 0x8230) binr.ReadInt16(); else return null; bt = binr.ReadByte(); if (bt != 0x02) return null; twobytes = binr.ReadUInt16(); if (twobytes != 0x0001) return null; seq = binr.ReadBytes(15); if (!CompareBytearrays(seq, SeqOID)) return null; bt = binr.ReadByte(); if (bt != 0x04) return null; bt = binr.ReadByte(); if (bt == 0x81) binr.ReadByte(); else if (bt == 0x82) binr.ReadUInt16(); byte[] rsaprivkey = binr.ReadBytes((int)(lenstream - mem.Position)); RSACryptoServiceProvider rsacsp = DecodeRSAPrivateKey(rsaprivkey); return rsacsp; } catch (Exception) { return null; } finally { binr.Close(); } } private static bool CompareBytearrays(byte[] a, byte[] b) { if (a.Length != b.Length) return false; int i = 0; foreach (byte c in a) { if (c != b[i]) return false; i++; } return true; } /// /// 处理私钥 /// /// ///private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey) { byte[] MODULUS, E, D, P, Q, DP, DQ, IQ; MemoryStream mem = new MemoryStream(privkey); BinaryReader binr = new BinaryReader(mem); byte bt = 0; ushort twobytes = 0; int elems = 0; try { twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) binr.ReadByte(); else if (twobytes == 0x8230) binr.ReadInt16(); else return null; twobytes = binr.ReadUInt16(); if (twobytes != 0x0102) return null; bt = binr.ReadByte(); if (bt != 0x00) return null; elems = GetIntegerSize(binr); MODULUS = binr.ReadBytes(elems); elems = GetIntegerSize(binr); E = binr.ReadBytes(elems); elems = GetIntegerSize(binr); D = binr.ReadBytes(elems); elems = GetIntegerSize(binr); P = binr.ReadBytes(elems); elems = GetIntegerSize(binr); Q = binr.ReadBytes(elems); elems = GetIntegerSize(binr); DP = binr.ReadBytes(elems); elems = GetIntegerSize(binr); DQ = binr.ReadBytes(elems); elems = GetIntegerSize(binr); IQ = binr.ReadBytes(elems); CspParameters cspParams = new CspParameters(); cspParams.Flags = CspProviderFlags.UseMachineKeyStore; //System.Security.Cryptography.RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, cspParams); RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024); RSAParameters RSAparams = new RSAParameters(); RSAparams.Modulus = MODULUS; RSAparams.Exponent = E; RSAparams.D = D; RSAparams.P = P; RSAparams.Q = Q; RSAparams.DP = DP; RSAparams.DQ = DQ; RSAparams.InverseQ = IQ; RSA.ImportParameters(RSAparams); return RSA; } catch (Exception) { return null; } finally { binr.Close(); } } /// /// 获取binr的长度 /// /// ///private static int GetIntegerSize(BinaryReader binr) { byte bt = 0; byte lowbyte = 0x00; byte highbyte = 0x00; int count = 0; bt = binr.ReadByte(); if (bt != 0x02) return 0; bt = binr.ReadByte(); if (bt == 0x81) count = binr.ReadByte(); else if (bt == 0x82) { highbyte = binr.ReadByte(); lowbyte = binr.ReadByte(); byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; count = BitConverter.ToInt32(modint, 0); } else { count = bt; } while (binr.ReadByte() == 0x00) { count -= 1; } binr.BaseStream.Seek(-1, SeekOrigin.Current); return count; } } }
在主程序中添加如下代码:
using System; using Android.App; using Android.Widget; using Android.OS; using Java.Net; namespace App1 { [Activity(Label = "App1", MainLauncher = true)] public class MainActivity : Activity { // 合作商户ID。用签约支付宝账号登录ms.alipay.com后,在账户信息页面获取。 public static string PARTNER = "替换你支付宝申请的partner"; // 商户收款的支付宝账号 public static string SELLER = "替换你支付宝申请的seller"; //商户私密 string RSA_PRIVATE = "替换你支付宝申请的private_key"; ; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); Button button = FindViewById
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;
}
public String MySignType
{
get
{
return "sign_type=\"RSA\"";
}
}
#endregion
}
}
源代码见附件