/// <summary> /// 生成签名 /// </summary> /// <param name="param">待签名参数</param> /// <returns></returns> private string CreateSign(PaymentParam param) { var temp = new PaymentParam(param); //temp.Add("key", "psL6ocgtbjeJKsGb4nslFZiYclpRQ0ik"); temp.Add("key", Platform.PrivateKey); return(Hash(temp.ToQueryString(), true)); }
/// <summary> /// 验证签名 /// </summary> /// <param name="param">待验证签名参数</param> /// <returns></returns> public bool VerifySign(PaymentParam param) { var sign = param.GetString("sign"); //获取返回时的签名验证结果 param = param.Remove("sign", "sign_type"); //移除不参与签名的参数 var isValid = RSA.Verify(CreateSign(param), sign, Platform.PublicKey, Charset); //验证是否是支付宝服务器发来的请求 var notifyId = param.GetString("notify_id"); if (isValid && !string.IsNullOrEmpty(notifyId)) { var reqParam = new PaymentParam(); reqParam.Add("service", "notify_verify"); reqParam.Add("partner", Platform.MerchantId); reqParam.Add("notify_id", notifyId); var url = reqParam.ToQueryString(true, true); var responseTxt = Client.GetStringAsync(url).Result; return(responseTxt.ToLower() == "true"); } return(false); }
/// <summary> /// 处理支付平台通知 /// </summary> /// <param name="param">第三方支付平台通知参数</param> /// <returns></returns> public override Result <Notification> HandleNotify(PaymentParam param) { var now = DateTime.Now; var input = param.ToXml(); var notification = new Notification(Platform.Id, input, "fail"); var result = new Result <Notification>(false, notification); var isValid = VerifySign(param); if (isValid) { var reqParam = new PaymentParam(); var notifyId = param.GetString("notify_id"); // 通知id reqParam.Add("notify_id", notifyId); reqParam.Add("partner", Platform.MerchantId); reqParam.Add("sign", CreateSign(reqParam)); //系统可选参数 reqParam.Add("sign_type", "MD5"); reqParam.Add("service_version", "1.0"); reqParam.Add("input_charset", "UTF-8"); reqParam.Add("sign_key_index", "1"); var url = "https://gw.tenpay.com/gateway/verifynotifyid.xml" + reqParam.ToQueryString(true); var xml = XElement.Load(url); var notifyParam = new PaymentParam(xml); result.Data.PayId = notifyParam.GetString("out_trade_no"); //系统支付单号 result.Data.PayNo = notifyParam.GetString("transaction_id"); // 财付通交易号,28位长的数值,其中前10位为商户号,之后8位为订单产生的日期; result.Data.Amount = notifyParam.GetInt("total_fee") / 100M; // 转换为元为单位; result.Data.PaidOn = notifyParam.GetDateTime("time_end", now); result.Data.State = param.GetString("attach"); //扩展字段 支付平台原样返回 var bankOrderNo = notifyParam.GetString("bank_billno"); // 银行订单号,若为财付通余额支付则为空 if (VerifySign(notifyParam) && notifyParam["retcode"] == "0" && notifyParam["trade_state"] == "0" && notifyParam["trade_mode"] == "1") { var status = OnNotified(notification); if (status) { result.Status = true; result.Data.SetOutput("success"); } else { result.Message = "TenPay OnNotified 返回false"; } } else { result.Message = "TenPay 通知验证失败"; } } else { result.Message = "TenPay 签名验证失败"; } return(result); }
/// <summary> /// 生成支付所需信息 url json等 /// </summary> /// <param name="payment">付款信息</param> /// <param name="exts">其他参数信息</param> /// <returns></returns> public override string Pay(Payment payment, params string[] exts) { var param = new PaymentParam(); var payId = payment.Id; //系统订单号 //var payNo = payment.PayNo;//支付平台订单号 var amount = payment.Amount * 100; //转换为分 var gateway = payment.BankCode; //系统可选参数 param.Add("sign_type", "MD5"); param.Add("service_version", "1.0"); param.Add("input_charset", "UTF-8"); param.Add("sign_key_index", "1"); //业务参数 是否必填 类型 说明 param.Add("bank_type", gateway); // 否 String(16) 银行类型,默认为“DEFAULT”-财付通支付中心。银行直连编码及额度请与技术支持联系 param.Add("body", "test"); // 是 String(32) 商品描述 param.Add("attach", payment.State); // 否 String(127) 附加数据,原样返回 param.Add("return_url", Platform.CallbackUrl); // 是 String(255) 交易完成后跳转的URL,需给绝对路径,255字符内,格式如:http://wap.tenpay.com/tenpay.asp,通过该路径直接将支付结果以Get的方式返回 param.Add("notify_url", Platform.NotifyUrl); // 是 String(255) 接收财付通通知的URL,需给绝对路径,255字符内,格式如:http://wap.tenpay.com/tenpay.asp //param.Add("buyer_id ", ""); // 否 String(64) 买方的财付通账户(QQ 或EMAIL)。若商户没有传该参数,则在财付通支付页面,买家需要输入其财付通账户。 param.Add("partner", Platform.MerchantId); // 是 String(10) 商户号,由财付通统一分配的10位正整数(120XXXXXXX)号 param.Add("out_trade_no", payId); // 是 String(32) 商户系统内部的订单号,32个字符内、可包含字母,确保在商户系统唯一 param.Add("total_fee ", amount.ToString("F0")); // 是 Int 订单总金额,单位为分 param.Add("fee_type ", "1"); // 是 Int 现金支付币种,取值:1(人民币),默认值是1,暂只支持1 param.Add("spbill_create_ip", payment.IpAddress); // 是 String(15) 订单生成的机器IP,指用户浏览器端IP,不是商户服务器IP 测试时填写127.0.0.1,只能支持10分以下交易 //业务可选参数 /* * param.Add("time_start", ""); //否 String(14) 订单生成时间,格式为yyyyMMddhhmmss,如2009年12月25日9点10分10秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器 * param.Add("time_expire", ""); // 否 String(14) 订单失效时间,格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自商户服务器 * param.Add("transport_fee", ""); // 否 Int 物流费用,单位为分。如果有值,必须保证transport_fee + product_fee=total_fee * param.Add("product_fee", ""); // 否 Int 商品费用,单位为分。如果有值,必须保证transport_fee + product_fee=total_fee * param.Add("goods_tag", ""); // 否 String(32) 商品标记,优惠券时可能用到 */ param.Add("sign", CreateSign(param)); //获取带参数的url return(Platform.GatewayUrl + param.ToQueryString(true)); }
/// <summary> /// 生成支付所需信息 url json等 /// </summary> /// <param name="payment">付款信息</param> /// <param name="exts">其他参数信息</param> /// <returns></returns> public override string Pay(Payment payment, params string[] exts) { //测试 正式删除 开始 payment.Id = "X" + getRandomValidate(8);//"5950483"; payment.Subject = "test"; payment.Amount = 0.01m; Platform.MerchantId = "2088501709692126"; Platform.NotifyUrl = "http://shopping.tiantian.com/ToPay/MobilePayMent/APPPay/ZhiFuBaoCallBack.aspx"; var payId = payment.Id;//系统订单号 var amount = payment.Amount.ToString("F2"); var body = "test-body"; //测试 正式删除 结束 var param = new Dictionary <string, string>(); // 支付宝支付接口必需参数 参数顺序必需固定且与react native里android一致 因为签名原因 param.Add("service", "mobile.securitypay.pay");//接口名称,固定值 param.Add("partner", Platform.MerchantId); param.Add("_input_charset", Charset); param.Add("notify_url", Platform.NotifyUrl); param.Add("out_trade_no", payId); param.Add("subject", payment.Subject); //商品的标题/交易标题/订单标题/订单关键字等。该参数最长为128个汉字。 param.Add("payment_type", PaymentType); param.Add("seller_id", Platform.MerchantId); //卖家支付宝账号(邮箱或手机号码格式)或其对应的支付宝唯一用户号(以2088开头的纯16位数字) param.Add("total_fee", amount); param.Add("body", body); //对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body //connect = "partner=2088501709692126&[email protected]&out_trade_no=5950483&subject=订单编号5950483&body=订单编号5950483&total_fee=17.9¬ify_url=http://shopping.tiantian.com/ToPay/MobilePayMent/APPPay/ZhiFuBaoCallBack.aspx&service=mobile.securitypay.pay&_input_charset=utf-8&payment_type=1&return_url=http://www.tiantian.com&it_b_pay=1d&show_url=http://www.tiantian.com"; var sign = UrlEncoder.Default.Encode(CreateSign(param)); var output = new PaymentParam(); output.Add("partner", Platform.MerchantId); output.Add("seller", Platform.MerchantId); output.Add("outTradeNO", payId); output.Add("subject", payment.Subject); output.Add("body", body); output.Add("totalFee", amount); output.Add("notifyURL", Platform.NotifyUrl); output.Add("sign", sign); return(output.ToJson());//生成适用于react-native json格式的数据 /* 2.0 * // 支付宝支付接口必需参数 * param.Add("app_id", "2015010900024452"); * param.Add("method", "alipay.trade.app.pay"); * param.Add("charset", Charset); * param.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); * param.Add("version", "1.0"); * param.Add("notify_url", Platform.NotifyUrl); * * * var biz = new PaymentParam(); * biz.Add("out_trade_no", payment.Id); * biz.Add("subject", payment.Subject); * biz.Add("body", body); * biz.Add("total_amount", amount); * biz.Add("product_code", "QUICK_MSECURITY_PAY"); * * param.Add("biz_content", biz.ToJson()); * * var sign = CreateSign(param); * * param.Add("sign", sign); * param.Add("sign_type", SignType); * * * var output = param.ToQueryString(false, true, true); * return output; */ /* * param.Add("privateKey", Platform.PrivateKey); * param.Add("partner", Platform.MerchantId); * param.Add("seller", SellerId); * param.Add("outTradeNO", payId); * param.Add("body", body); * param.Add("totalFee", amount); * param.Add("notifyURL", Platform.NotifyUrl); * param.Add("itBPay", "30m");//设置未付款交易的超时时间,一旦超时,该笔交易就会自动被关闭。当用户输入支付密码、点击确认付款后(即创建支付宝交易后)开始计时。取值范围:1m~15d,或者使用绝对时间(示例格式:2014-06-13 16:00:00)。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。该参数数值不接受小数点,如1.5h,可转换为90m。 * return param.ToJson();//生成适用于https://github.com/huangzuizui/rn-alipay json格式的数据 */ }
/// <summary> /// 生成支付所需信息 url json等 /// </summary> /// <param name="payment">付款信息</param> /// <param name="exts">其他参数信息</param> /// <returns></returns> public override string Pay(Payment payment, params string[] exts) { var param = new PaymentParam(); var payId = payment.Id;//系统订单号 var amount = payment.Amount.ToString("F2"); var body = "7shop24Product"; var showUrl = "http://www.tiantian.com"; param.Add("partner", Platform.MerchantId); param.Add("_input_charset", Charset); param.Add("service", "create_direct_pay_by_user"); param.Add("payment_type", PaymentType); param.Add("notify_url", Platform.NotifyUrl); param.Add("return_url", Platform.CallbackUrl); param.Add("seller_email", SellerEmail); param.Add("out_trade_no", payId); param.Add("subject", payment.Subject); param.Add("total_fee", amount); param.Add("body", body); param.Add("show_url", showUrl); //param.Add("anti_phishing_key", anti_phishing_key); param.Add("exter_invoke_ip", payment.IpAddress); param.Add("extra_common_param", payment.State);//支付平台原样返回 param.Add("sign", CreateSign(param)); param.Add("sign_type", SignType); return(Platform.GatewayUrl + param.ToQueryString(true, true, true)); }
private string Pay(Payment payment, string tradeType, string openId) { var param = new PaymentParam(); param.Add("appid", Platform.PublicKey); //微信分配的公众账号ID(企业号corpid即为此appId) param.Add("mch_id", Platform.MerchantId); //微信支付分配的商户号 param.Add("nonce_str", GenerateNonceStr()); //随机字符串,不长于32位 param.Add("body", payment.Subject); //商品简单描述 该字段须严格按照规范传递 param.Add("attach", payment.State); //附加数据 在查询API和支付通知中原样返回 该字段主要用于商户携带订单的自定义数据 param.Add("out_trade_no", payment.Id); //商户系统内部的订单号,32个字符内 可包含字母 param.Add("total_fee", (payment.Amount * 100).ToString("F0")); //订单总金额,单位为分 不能带小数 param.Add("spbill_create_ip", payment.IpAddress); //APP和网页支付提交用户端ip Native支付填调用微信支付API的机器IP param.Add("notify_url", Platform.NotifyUrl); param.Add("trade_type", tradeType); if (tradeType == "NATIVE") { param.Add("product_id", payment.Id);// trade_type = NATIVE 时 此参数必传 此id为二维码中包含的商品ID,商户自行定义 } if (tradeType == "JSAPI") { param.Add("openid", openId);// rade_type=JSAPI 时此参数必传 用户在商户appid下的唯一标识 } param.Add("sign", CreateSign(param)); PaymentParam data;//支付接口返回参数 using (Client) { var xml = param.ToXml();//微信接口接受xml格式的数据 OnTraced("微信支付 提交数据", xml); var hc = new StringContent(xml, Encoding.UTF8, "text/xml"); var rep = Client.PostAsync(Platform.GatewayUrl, hc).Result; var repXml = XElement.Load(rep.Content.ReadAsStreamAsync().Result); OnTraced("微信支付 返回数据", repXml.ToString()); data = new PaymentParam(repXml); } var s = string.Empty; if (data.GetString("return_code") == "SUCCESS" && data.GetString("result_code") == "SUCCESS") { if (VerifySign(data)) { if (tradeType == "APP") { var prePayParam = new PaymentParam(); var prePayId = data.GetString("prepay_id"); prePayParam.Add("appId", Platform.PublicKey); prePayParam.Add("partnerId", Platform.MerchantId); prePayParam.Add("prepayId", prePayId); prePayParam.Add("package", "Sign=WXPay"); prePayParam.Add("nonceStr", GenerateNonceStr()); prePayParam.Add("timeStamp", GenerateTimeStamp()); prePayParam.Add("sign", CreateSign(prePayParam)); s = prePayParam.ToJson(); } else if (tradeType == "JSAPI") { var prePayParam = new PaymentParam(); var prePayId = data.GetString("prepay_id"); prePayParam.Add("appId", Platform.PublicKey); prePayParam.Add("timeStamp", GenerateTimeStamp()); prePayParam.Add("nonceStr", GenerateNonceStr()); prePayParam.Add("package", "prepay_id=" + prePayId); prePayParam.Add("signType", "MD5"); prePayParam.Add("paySign", CreateSign(prePayParam)); s = prePayParam.ToJson(); } else if (tradeType == "NATIVE") { s = data.GetString("code_url");//用于生成微信客户端可识别的支付URL } } else { var err = data.GetString("err_code_des"); var msg = string.IsNullOrEmpty(err) ? data.GetString("return_msg") : err; OnTraced("微信支付 验证返回数据签名失败", msg); } } return(s); }