第三方支付系统开发APP方案开发要多少钱

App应用软件制作开发的成本要多少钱?_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
赠送免券下载特权
10W篇文档免费专享
部分付费文档8折起
每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
内容提供机构
更多优质内容和服务
App应用软件制作开发的成本要多少钱?
0|0|暂无简介|
信息科技、计算机软硬件、电子产品、通信设...|
总评分0.0|
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
还剩7页未读,点击继续
梦思特信息科技(上海)有限公司
文库认证机构官网
信息科技、计算机软硬件、电子产品、通信设备领域内的技术开发、技术咨询、技术服务、技术转让,计算机系统集成,市场营销策划,商务信息咨询、企业管理咨询(以...已解决问题
一款APP支付系统,需要第三方支付牌照吗?
提问时间: 04:34:24
有一款APP,有3个主体,用户、平台、商户。(类似于易道用车)用户充值到平台以冲100得120,冲200得300,冲300得500。(后缀可能是X币)然后用户在商户那消费后,直接扫描商户的二维码,把充值的币直接转账到商户账户,商户可以向平台申请,把这些币提现到商户支付宝账户(扣除一定服务费)。 这种模式下,需不需要第三方支付牌照?
浏览次数:9102
该答案已经被保护
题主描述的问题涉及如下几方面: 1、移动支付厂商的选型 1.1、支付渠道 由于是APP,采用的支付方式主要大致有如下几种方式: a、APP SDK 支持银行卡支付(借记卡、信用卡)、账户支付、快捷支付等。 1.2、增值服务 对普通商户而言,在选择第三方支付厂商时候,除了考了支付渠道、交易手续费外,还需要重点考虑第三方支付提供的其他服务,主要包括如下一些方面: a、结算周期、结算手续费 b、提现/退款接口 c、分账/代付(委托结算)等结算服务:例如对代理商按照自定义规则对交易进行分账并批量代付到指定的银行账号(对公、对私) 一般而言,支付宝、财付通(微信支付)、银联在线对分账/代付支持较弱,而像块钱/汇付/易宝之类独立第三方支付,在结算服务商策略相对灵活、产品解决方案也相对完善。拆单的目的是为了成功支付订单 但是将一笔大金额的支付单拆成几笔小金额的支付单有几方面的问题: 1.在快捷支付的场景下,对银行而言都是客户发起的代扣交易,你在页面展示的是一笔支付,实际扣了两笔,较真的客户可以要求你赔偿第二笔代扣的钱(第二笔客户没授权),有法律风险。 如果是对公账户: 1、大额支付的限额,如果通过企业网银走,一般对额度应该没有太多限制(假定在几百万内),如果此种方案可行,干嘛一定要去分多笔代扣充值。
答案创立者
以企业身份回答&
快速解决你的电商难题
店铺优化排查提升2倍流量
擅长&nbsp 店铺优化
您可能有同感的问题第三方支付功能开发之支付宝APP端支付(java教程)
这里只涉及java后台,不涉及APP端的代码。
1、生成订单信息,给APP
@ApiOperation(value = &根据订单ID获取支付宝订单详情&, notes = &根据订单ID获取支付宝订单详情[@黄超飞&)
@RequestMapping(value = &createAlipay/{orderId}&, method = RequestMethod.GET)
@ResponseBody
public RestResponse createAlipay(@PathVariable Integer orderId) throws Exception {
ShareOrderInfo order = new ShareOrderInfo();
order.setId(orderId);
order = shareOrderInfoService.selectByPrimaryKey(order);
if(order == null){
return new RestResponse&&(HttpStatus.BAD_REQUEST.getValue(), &根据订单ID查询不到订单信息&, null);
String out_trad_no = &APP_ALIPAY& + OrderNoUtil.leadsNo();
//保存预支付交易流水
User user = getUser();
if (user == null) {
return new RestResponse&&(HttpStatus.NEED_LOGIN.getValue(), &未登录&, null);
ShareUserTrad shareUserTrad = new ShareUserTrad();
shareUserTrad.setResourceTradId(-1);
shareUserTrad.setUserId(user.getId());
shareUserTrad.setCreatedBy(user.getId());
shareUserTrad.setLastUpdBy(user.getId());
shareUserTrad.setOnlineOfflineFlag(&0&);//线上
shareUserTrad.setOrderNo(order.getOrderNo());
shareUserTrad.setUserTradAmount(order.getToBePaid());
shareUserTrad.setTradMethod(&3&);//支付宝
shareUserTrad.setPayReceiveFlag(&2&);//支出
shareUserTrad.setSuccessFlag(&0&);//交易进行中
shareUserTrad.setTradType(&1&);//订单支付
shareUserTrad.setTradNo(out_trad_no);
shareUserTrad.setModifyNum(0);
shareUserTradMapper.insertSelective(shareUserTrad);
Map keyValues = new HashMap();
SimpleDateFormat sdf = new SimpleDateFormat(&yyyy-MM-dd HH:mm:ss&);
keyValues.put(&app_id&, Config.alipay_app_id);
keyValues.put(&biz_content&, &{& +
&\&product_code\&:\&QUICK_MSECURITY_PAY\&,& +
&\&total_amount\&:\&0.01\&,& +
&\&subject\&:\&订单支付\&,& +
&\&body\&:\&订单号[&+order.getOrderNo()+&]用户在APP上使用支付宝支付.\&,& +
&\&out_trade_no\&:\&& + out_trad_no +
keyValues.put(&charset&, Config.alipay_charset);
keyValues.put(&method&, &alipay.trade.app.pay&);
keyValues.put(&sign_type&, Config.alipay_sign_type);
keyValues.put(&version&, &1.0&);
keyValues.put(&timestamp&, sdf.format(new Date()));
keyValues.put(&notify_url&, Config.alipay_notify_url);//回调地址
String orderParam = AlipayOrderUtil.buildOrderParam(keyValues);
String sign = AlipayOrderUtil.getSign(keyValues, Config.alipay_private_key, true);
String orderInfo = orderParam + &&& +
return new RestResponse&&(HttpStatus.OK.getValue(),&保存预支付交易流水成功&,orderInfo);
支付宝出于安全考虑要请求在后台生成订单信息,而不是在APP端生成。
AlipayOrderUtil:
import java.io.UnsupportedEncodingE
import java.net.URLE
import java.text.SimpleDateF
import java.util.*;
public class AlipayOrderUtil {
* 构造授权参数列表
* @param pid
* @param app_id
* @param target_id
public static Map buildAuthInfoMap(String pid, String app_id, String target_id, boolean rsa2) {
Map keyValues = new HashMap();
// 商户签约拿到的app_id,如:4223
keyValues.put(&app_id&, app_id);
// 商户签约拿到的pid,如:6631
keyValues.put(&pid&, pid);
// 服务接口名称, 固定值
keyValues.put(&apiname&, &com.alipay.account.auth&);
// 商户类型标识, 固定值
keyValues.put(&app_name&, &mc&);
// 业务类型, 固定值
keyValues.put(&biz_type&, &openservice&);
// 产品码, 固定值
keyValues.put(&product_id&, &APP_FAST_LOGIN&);
// 授权范围, 固定值
keyValues.put(&scope&, &kuaijie&);
// 商户唯一标识,如:kkkkk091125
keyValues.put(&target_id&, target_id);
// 授权类型, 固定值
keyValues.put(&auth_type&, &AUTHACCOUNT&);
// 签名类型
keyValues.put(&sign_type&, rsa2 ? &RSA2& : &RSA&);
return keyV
* 构造支付订单参数列表
public static Map buildOrderParamMap(String app_id, boolean rsa2) {
Map keyValues = new HashMap();
keyValues.put(&app_id&, app_id);
keyValues.put(&biz_content&, &{\&timeout_express\&:\&30m\&,\&product_code\&:\&QUICK_MSECURITY_PAY\&,\&total_amount\&:\&0.01\&,\&subject\&:\&1\&,\&body\&:\&我是测试数据\&,\&out_trade_no\&:\&& + getOutTradeNo() +
keyValues.put(&charset&, &utf-8&);
keyValues.put(&method&, &alipay.trade.app.pay&);
keyValues.put(&sign_type&, rsa2 ? &RSA2& : &RSA&);
keyValues.put(&timestamp&, & 16:55:53&);
keyValues.put(&version&, &1.0&);
return keyV
* 构造支付订单参数信息
* @param map
* 支付订单参数
public static String buildOrderParam(Map map) {
List keys = new ArrayList(map.keySet());
StringBuilder sb = new StringBuilder();
for (int i = 0; i & keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
sb.append(buildKeyValue(key, value, true));
sb.append(&&&);
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
sb.append(buildKeyValue(tailKey, tailValue, true));
return sb.toString();
* 拼接键值对
* @param key
* @param value
* @param isEncode
private static String buildKeyValue(String key, String value, boolean isEncode) {
StringBuilder sb = new StringBuilder();
sb.append(key);
sb.append(&=&);
if (isEncode) {
sb.append(URLEncoder.encode(value, &UTF-8&));
} catch (UnsupportedEncodingException e) {
sb.append(value);
sb.append(value);
return sb.toString();
* 对支付参数信息进行签名
* @param map
待签名授权信息
public static String getSign(Map map, String rsaKey, boolean rsa2) {
List keys = new ArrayList(map.keySet());
// key排序
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
for (int i = 0; i & keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
authInfo.append(buildKeyValue(key, value, false));
authInfo.append(&&&);
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
authInfo.append(buildKeyValue(tailKey, tailValue, false));
String oriSign = SignUtils.sign(authInfo.toString(), rsaKey, rsa2);
String encodedSign = &&;
encodedSign = URLEncoder.encode(oriSign, &UTF-8&);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return &sign=& + encodedS
* 要求外部订单号必须唯一。
private static String getOutTradeNo() {
SimpleDateFormat format = new SimpleDateFormat(&MMddHHmmss&, Locale.getDefault());
Date date = new Date();
String key = format.format(date);
Random r = new Random();
key = key + r.nextInt();
key = key.substring(0, 15);
public final class Base64 {
private static final int BASELENGTH = 128;
private static final int LOOKUPLENGTH = 64;
private static final int TWENTYFOURBITGROUP = 24;
private static final int EIGHTBIT = 8;
private static final int SIXTEENBIT = 16;
private static final int FOURBYTE = 4;
private static final int SIGN = -128;
private static char PAD = '=';
private static byte[] base64Alphabet = new byte[BASELENGTH];
private static char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
for (int i = 0; i & BASELENGTH; ++i) {
base64Alphabet[i] = -1;
for (int i = 'Z'; i &= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
for (int i = 'z'; i &= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
for (int i = '9'; i &= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
for (int i = 0; i &= 25; i++) {
lookUpBase64Alphabet[i] = (char) ('A' + i);
for (int i = 26, j = 0; i &= 51; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('a' + j);
for (int i = 52, j = 0; i &= 61; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('0' + j);
lookUpBase64Alphabet[62] = (char) '+';
lookUpBase64Alphabet[63] = (char) '/';
private static boolean isWhiteSpace(char octect) {
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
private static boolean isPad(char octect) {
return (octect == PAD);
private static boolean isData(char octect) {
return (octect & BASELENGTH && base64Alphabet[octect] != -1);
* Encodes hex octects into Base64
* @param binaryData
Array containing binaryData
* @return Encoded Base64 array
public static String encode(byte[] binaryData) {
if (binaryData == null) {
int lengthDataBits = binaryData.length * EIGHTBIT;
if (lengthDataBits == 0) {
return &&;
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
char encodedData[] =
encodedData = new char[numberQuartet * 4];
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
int encodedIndex = 0;
int dataIndex = 0;
for (int i = 0; i & numberT i++) {
b1 = binaryData[dataIndex++];
b2 = binaryData[dataIndex++];
b3 = binaryData[dataIndex++];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 && 2)
: (byte) ((b1) && 2 ^ 0xc0);
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 && 4)
: (byte) ((b2) && 4 ^ 0xf0);
byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 && 6)
: (byte) ((b3) && 6 ^ 0xfc);
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k && 4)];
encodedData[encodedIndex++] = lookUpBase64Alphabet[(l && 2) | val3];
encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
// form integral number of 6-bit groups
if (fewerThan24bits == EIGHTBIT) {
b1 = binaryData[dataIndex];
k = (byte) (b1 & 0x03);
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 && 2)
: (byte) ((b1) && 2 ^ 0xc0);
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[k && 4];
encodedData[encodedIndex++] = PAD;
encodedData[encodedIndex++] = PAD;
} else if (fewerThan24bits == SIXTEENBIT) {
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 && 2)
: (byte) ((b1) && 2 ^ 0xc0);
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 && 4)
: (byte) ((b2) && 4 ^ 0xf0);
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k && 4)];
encodedData[encodedIndex++] = lookUpBase64Alphabet[l && 2];
encodedData[encodedIndex++] = PAD;
return new String(encodedData);
* Decodes Base64 data into octects
* @param encoded
string containing Base64 data
* @return Array containind decoded data.
public static byte[] decode(String encoded) {
if (encoded == null) {
char[] base64Data = encoded.toCharArray();
// remove white spaces
int len = removeWhiteSpace(base64Data);
if (len % FOURBYTE != 0) {
// should be pisible by four
int numberQuadruple = (len / FOURBYTE);
if (numberQuadruple == 0) {
return new byte[0];
byte decodedData[] =
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
int i = 0;
int encodedIndex = 0;
int dataIndex = 0;
decodedData = new byte[(numberQuadruple) * 3];
for (; i & numberQuadruple - 1; i++) {
if (!isData((d1 = base64Data[dataIndex++]))
|| !isData((d2 = base64Data[dataIndex++]))
|| !isData((d3 = base64Data[dataIndex++]))
|| !isData((d4 = base64Data[dataIndex++]))) {
}// if found &no data& just return null
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[encodedIndex++] = (byte) (b1 && 2 | b2 && 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) && 4) | ((b3 && 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 && 6 | b4);
if (!isData((d1 = base64Data[dataIndex++]))
|| !isData((d2 = base64Data[dataIndex++]))) {
// if found &no data& just return null
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
d3 = base64Data[dataIndex++];
d4 = base64Data[dataIndex++];
if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
if (isPad(d3) && isPad(d4)) {
if ((b2 & 0xf) != 0)// last 4 bits should be zero
byte[] tmp = new byte[i * 3 + 1];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex] = (byte) (b1 && 2 | b2 && 4);
} else if (!isPad(d3) && isPad(d4)) {
b3 = base64Alphabet[d3];
if ((b3 & 0x3) != 0)// last 2 bits should be zero
byte[] tmp = new byte[i * 3 + 2];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex++] = (byte) (b1 && 2 | b2 && 4);
tmp[encodedIndex] = (byte) (((b2 & 0xf) && 4) | ((b3 && 2) & 0xf));
} else { // No PAD e.g 3cQl
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[encodedIndex++] = (byte) (b1 && 2 | b2 && 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) && 4) | ((b3 && 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 && 6 | b4);
return decodedD
* remove WhiteSpace from MIME containing encoded Base64 data.
* @param data
the byte array of base64 data (with WS)
* @return the new length
private static int removeWhiteSpace(char[] data) {
if (data == null) {
// count characters that's not whitespace
int newSize = 0;
int len = data.
for (int i = 0; i & i++) {
if (!isWhiteSpace(data[i])) {
data[newSize++] = data[i];
return newS
import org.bouncycastle.jce.provider.BouncyCastleP
import sun.misc.BASE64D
import java.security.*;
import java.security.spec.PKCS8EncodedKeyS
public class SignUtils {
private static final String ALGORITHM = &RSA&;
private static final String SIGN_ALGORITHMS = &SHA1WithRSA&;
private static final String SIGN_SHA256RSA_ALGORITHMS = &SHA256WithRSA&;
private static final String DEFAULT_CHARSET = &UTF-8&;
private static String getAlgorithms(boolean rsa2) {
return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;
Security.addProvider(new BouncyCastleProvider());
}catch(Exception e){
e.printStackTrace();
public static String sign(String content, String privateKey, boolean rsa2) {
MessageDigest messageDigest = MessageDigest.getInstance(&SHA-256&);
messageDigest.update(content.getBytes());
byte[] outputDigest_sign = messageDigest.digest();
Signature Sign = Signature.getInstance(&SHA256withRSA&);
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(privateKey));
KeyFactory keyf = KeyFactory.getInstance(&RSA&);
Sign.initSign(keyf.generatePrivate(priPKCS8));
Sign.update(outputDigest_sign);
byte[] signed = Sign.sign();
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance(ALGORITHM,&BC&);
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature
.getInstance(getAlgorithms(rsa2));
signature.initSign(priKey);
signature.update(content.getBytes(DEFAULT_CHARSET));
byte[] signed = signature.sign();
return Base64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
本来参考支付宝的demo,发现不能用,网上找原来是SignUtil出了问题,修改如下:
KeyFactory keyf = KeyFactory.getInstance(ALGORITHM,&BC&);
KeyFactory构造函数加上参数字符串&BC&,有些加上后可能会报错,加上静态代码段:
Security.addProvider(new BouncyCastleProvider());
}catch(Exception e){
e.printStackTrace();
就可以了。一款App的开发成本是多少? - 知乎<strong class="NumberBoard-itemValue" title="被浏览<strong class="NumberBoard-itemValue" title="4,048分享邀请回答1添加评论分享收藏感谢收起}

我要回帖

更多关于 第三方支付方案 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信